C# .NET MVC Core 3.1本地化和#x27;我不能接受当前的文化

C# .NET MVC Core 3.1本地化和#x27;我不能接受当前的文化,c#,asp.net-core,asp.net-core-mvc,asp.net-core-3.1,asp.net-core-localization,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core 3.1,Asp.net Core Localization,我正在将.NET4.7应用程序转换为.NETCore3.1。我正在更新本地化部分。我举了一些例子,比如 它工作得很好,但我没有找到一种方法使UrlHelper.Action在没有精确文化的情况下工作。 我想自动设置区域性参数。它应该来自userclaims、以前的请求区域性或默认区域性 例如,如果URL为“/Home/Contact”,则生成链接的UrlHelper或HtmlHelper将为/Home/About。 如果当前URL为“/en/Home/Contact”,则链接将生成为“/en/H

我正在将.NET4.7应用程序转换为.NETCore3.1。我正在更新本地化部分。我举了一些例子,比如

它工作得很好,但我没有找到一种方法使UrlHelper.Action在没有精确文化的情况下工作。 我想自动设置区域性参数。它应该来自userclaims、以前的请求区域性或默认区域性

例如,如果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应该保持lile“API/SomeStuff”

Startup.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?}");
});

如果缺少区域性,是否有方法使Urlhelper从当前上下文添加该区域性?

由于您在.NET Core中,因此应使用替换
Url.Action
方法

通过使用标记帮助器,您可以使用以下内容:

<a asp-controller="MyController" asp-action="DisplayItem" asp-route-number="123">Click</a>
  • 修改
    Shared/_ViewImports.cshtml
    以删除当前的
    AnchorTagHelper
    ,并使用新创建的标记帮助程序,如下所示:
  • 应用所有更改后的标记后,使用标记辅助对象时将填充区域性


    Url.Action根据路由模板生成Url。通用模板是将区域性放在根路径(/controller/culture/)之后。我会将您的答案标记为正确答案。但我还是很失望。我必须重写我的应用程序的上千个链接中的每一个。。。。
    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
    
    <a asp-controller="MyController" asp-action="DisplayItem" asp-route-number="123">Click</a>
    
    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);
            }
        }
    }
    
    
    @removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
    @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
    @addTagHelper *, YourMvcName