Пользовательские локализованные маршруты, использующие IApplicationModelConvention, не учитываются в IUrlHelper.GetVirtualPathData - PullRequest
0 голосов
/ 26 октября 2018

В настоящее время я портирую приложение из 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 s в своих IApplicationModelConvention.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...