1

我正在将 .Net 4.7 应用程序转换为 .Net Core 3.1。我正在更新本地化部分。我遵循了一些示例,例如localization-in-asp-net-core-3-1-mvc

它工作正常,但我没有找到一种方法让 UrlHelper.Action 在没有精确文化的情况下工作。我想自动设置文化参数。它应该来自用户声明、以前的请求文化或默认文化。

例如,如果 URL 是“/Home/Contact”,则 UrlHelper 或 HtmlHelper 生成的链接将是 /Home/About。如果当前 URL 为“/en/Home/Contact”,则链接将生成为“/en/Home/About”。如果用户通过身份验证,则应该是“/userCulture/Home/About”。

但我不能只强制我的路由模板 "{culture=en}/{controller=Home}/{action=Welcome}/{id?}" 因为根 url 必须可访问并且 API url 应该保持 "api/somestufff" .

启动.cs:

var supportedCultures = CultureHelper.Cultures.Select(a => new CultureInfo(a)).ToArray();
var requestLocalizationOptions = new RequestLocalizationOptions();
requestLocalizationOptions.SupportedCultures = supportedCultures;
services.AddLocalization();
services.Configure<RequestLocalizationOptions>(options =>
{
    options.DefaultRequestCulture = new RequestCulture("fr", "fr");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
    options.RequestCultureProviders.Insert(0, new RouteValueRequestCultureProvider() { Options = requestLocalizationOptions });
});

//......................................

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(name: "culture-route", pattern: "{culture=en}/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
});

控制器 :

[Route("api/somestufff")]
public async Task<IActionResult> Somestufff()
{ ... }

[Route("{culture:length(2)}/items/{number:int}/{permalink?}")]
public async Task<IActionResult> DisplayItem(int number, string permalink)
{ ... }

剃刀页面:

Url.Action("DisplayItem", "MyController",new { culture = ViewBag.Culture as string, number = 123, permalink = "permalink1235" }) 
// => /en/items/123/permalink1235 OK

Url.Action("DisplayItem", "MyController",new { number = 123, permalink = "permalink1235"  }) 
// => /en/MyController/DisplayItem?number=123&permalink=permalink1235 KO

如果缺少,有没有办法让 Urlhelper 从当前上下文中添加文化?

4

1 回答 1

1

由于您在 .NET Core 中,因此您应该Url.Action使用Tag helpers替换这些方法。

通过使用标签助手,您可以使用如下内容:

<a asp-controller="MyController" asp-action="DisplayItem" asp-route-number="123">Click</a>

这显然不能解决culture你的路线,我们将在一分钟内解决。

当前处理标签asp-属性的标签持有者aAnchorTagHelper.Microsoft.AspNetCore.Mvc.TagHelpers

我们可以继承该类并添加有关处理culture.

  1. CultureAnchorTagHelper在您的 MVC 项目中创建一个名为的类/TagHelpers
  2. 填写内容如下:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace YourMvcName.TagHelpers
{
    [HtmlTargetElement("a", Attributes = ActionAttributeName)]
    [HtmlTargetElement("a", Attributes = ControllerAttributeName)]
    [HtmlTargetElement("a", Attributes = AreaAttributeName)]
    [HtmlTargetElement("a", Attributes = PageAttributeName)]
    [HtmlTargetElement("a", Attributes = PageHandlerAttributeName)]
    [HtmlTargetElement("a", Attributes = FragmentAttributeName)]
    [HtmlTargetElement("a", Attributes = HostAttributeName)]
    [HtmlTargetElement("a", Attributes = ProtocolAttributeName)]
    [HtmlTargetElement("a", Attributes = RouteAttributeName)]
    [HtmlTargetElement("a", Attributes = RouteValuesDictionaryName)]
    [HtmlTargetElement("a", Attributes = RouteValuesPrefix + "*")]
    public class CultureAnchorTagHelper : AnchorTagHelper
    {
        public CultureAnchorTagHelper(IHttpContextAccessor contextAccessor, IHtmlGenerator generator) :
            base(generator)
        {
            this.contextAccessor = contextAccessor;
        }

        private const string ActionAttributeName = "asp-action";
        private const string ControllerAttributeName = "asp-controller";
        private const string AreaAttributeName = "asp-area";
        private const string PageAttributeName = "asp-page";
        private const string PageHandlerAttributeName = "asp-page-handler";
        private const string FragmentAttributeName = "asp-fragment";
        private const string HostAttributeName = "asp-host";
        private const string ProtocolAttributeName = "asp-protocol";
        private const string RouteAttributeName = "asp-route";
        private const string RouteValuesDictionaryName = "asp-all-route-data";
        private const string RouteValuesPrefix = "asp-route-";
        private const string Href = "href";

        private readonly IHttpContextAccessor contextAccessor;
        private readonly string defaultRequestCulture = "en";

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            // Get the culture from the route values
            var culture = (string)contextAccessor.HttpContext.Request.RouteValues["culture"];
 
            // Set the culture in the route values if it is not null
            if (culture != null && culture != defaultRequestCulture)
            {
                // Remove the 'href' just in case
                output.Attributes.RemoveAll("href");
                RouteValues["culture"] = culture;
            }
           
            // Call the base class for all other functionality, we've only added the culture route value.
            // Because the route has the `{culture=en}`, the tag helper knows what to do with that route value.
            base.Process(context, output);
        }
    }
}

  1. 修改Shared/_ViewImports.cshtml删除 current AnchorTagHelper,并使用我们新创建的标签助手如下:
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, YourMvcName

应用所有更改后,当您使用标签助手时,将填写文化。

视觉工作室中的标签

标签的输出

于 2020-11-15T10:47:59.867 回答