IUrlHelper.GetVirtualPathData不遵循使用IApplicationModelConvention的自定义本地化路由。

时间:2018-10-26 14:26:21

标签: c# asp.net asp.net-core

我目前正在将应用程序从ASP.NET 4移植到ASP.NET Core。我想使用基于属性的路由,同时能够本地化URL。

旧版应用程序正在使用一种使用自定义IDirectRouteProvider的方法。由于我没有在ASP.NET Core中找到相应的类型,因此我选择了受https://www.strathweb.com/2015/11/localized-routes-with-asp-net-5-and-mvc-6/启发的解决方案。这是使用IApplicationModelConvention

的实现
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(o =>
            {
                o.Conventions.Insert(0, new LocalizedRouteConvention());
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.UseRequestLocalization(new RequestLocalizationOptions { ... });

        app.UseMvc();
    }
}

public class LocalizedRouteConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            foreach (var action in controller.Actions)
            {
                var attributes = action.Attributes.OfType<RouteAttribute>().ToArray();
                if (!attributes.Any()) return;

                foreach (var attribute in attributes)
                {
                    SelectorModel defaultSelector = action.Selectors.First();

                    foreach (var localizedVersion in GetLocalized(attribute.Template))
                    {
                        if (!action.Selectors.Any(s => s.AttributeRouteModel.Template == localizedVersion.Template))
                        {
                            action.Selectors.Insert(0, new SelectorModel(defaultSelector)
                            {
                                AttributeRouteModel = localizedVersion,
                                ActionConstraints =
                                {
                                    new CultureActionConstraint { Culture = ((LocalizedRouteAttribute) localizedVersion.Attribute).Culture }
                                }
                            });
                        }
                    }
                }
            }
        }
    }
}

public class LocalizedRouteAttribute : RouteAttribute
{
    public LocalizedRouteAttribute(string template) : base(template)
    {
    }

    public string Culture { get; set; }
}

public class CultureActionConstraint : IActionConstraint
{
    public string Culture { get; set; }

    public int Order => 0;

    public bool Accept(ActionConstraintContext context)
    {
        return CultureInfo.CurrentCulture.TwoLetterISOLanguageName == Culture;
    }
}

现在,此方法有效,并且只有在设置了正确的请求区域性时,本地化路由才可用。但是,当我使用Html.ActionLink(...)或使用IUrlHelper.GetVirtualPathData()的任何其他函数时,将返回默认路由,而不是本地化的路由。

据我了解,IUrlHelper将检查一条路线的IRouteConstraint,但似乎并不尊重IActionConstraint。不幸的是,我还没有找到在IRouteConstraint中设置自定义IApplicationModelConvention的方法。

0 个答案:

没有答案