在 asp net core 3.1 中使用 RouteDataRequestCultureProvider

Using RouteDataRequestCultureProvider in asp net core 3.1

从核心 2.2 升级到 3.1 我无法让 RouteDataRequestCultureProvider 完全工作。

路由有效,但 razor 标签助手忽略了文化和使用文化的路由属性。

作为自定义路由属性的简单示例:

public class StaticPageController : Controller
{
    [Route("{culture:culture}/cookies")]
    public IActionResult Cookies() => View();
}

如果我转到 url https://localhost:5002/en/cookies,操作将正确路由到。 但是在剃须刀中,如果我使用这样的助手:

<a asp-controller="StaticPage" asp-action="Cookies">Cookie information</a>

它生成的结果 link 是:https://localhost:5002/en/staticpage/cookies

在核心 2.2 中,这是正确生成 url https://localhost:5002/en/cookies

路由数据字典正确包含文化条目,但 razor 助手不再使用它并且默认为默认路由模式:

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

有谁知道为什么 razor 标签助手不再使用路由数据字典中的区域性?

编辑:

我现在知道文化不会从路由值传递到 url 生成器,因为它被认为是环境值,并且从核心 2.2 开始不再包括环境值。

Route Data values for the current request are considered ambient values in ASP.NET Core 2.1 and earlier

我可以通过明确指定文化来解决这个问题:

 <a 
    asp-controller="StaticPage" 
    asp-action="Cookies" asp-route- 
    culture="@Context.Request.RouteValues["culture"]">
       Cookies
 </a>

为每个页面上的每个 link 指定此项将非常乏味。

有没有办法覆盖 tag helper 以自动将当前文化包含在路由值中?

所以我最终解决了这个问题,方法是覆盖锚标记助手的工作方式并确保它始终从路由传递到文化中。

这是自定义标签助手:

[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
{
    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-";


    public CultureAnchorTagHelper(IHtmlGenerator generator, IHttpContextAccessor contextAccessor) : base(generator)
    {
        var culture = contextAccessor.HttpContext.Request.RouteValues["culture"]?.ToString() ?? "en";
        RouteValues["culture"] = culture;
    }
}

要使用它,您需要删除默认的锚标签助手并在 _ViewImports.cshtml:

中添加您自己的
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Your.Assembly.Namespace //assembly name containing class above

一些有用的链接:

@herostwist,你的解决方案救了我一命:)

只是它的一个简化版本:

//...
public CultureAnchorTagHelper(IHtmlGenerator generator) : base(generator)
{
    RouteValues["culture"] = CultureInfo.CurrentCulture.Name;
}