При желании можно переопределить культуру запроса через URL / маршрут в приложении ASP.NET Core 1.0

Я пытаюсь переопределить культуру текущего запроса. Я получил это работать частично с помощью обычаяActionFilterAttribute.

public sealed class LanguageActionFilter : ActionFilterAttribute
{
    private readonly ILogger logger;
    private readonly IOptions<RequestLocalizationOptions> localizationOptions;

    public LanguageActionFilter(ILoggerFactory loggerFactory, IOptions<RequestLocalizationOptions> options)
    {
        if (loggerFactory == null)
            throw new ArgumentNullException(nameof(loggerFactory));

        if (options == null)
            throw new ArgumentNullException(nameof(options));

        logger = loggerFactory.CreateLogger(nameof(LanguageActionFilter));
        localizationOptions = options;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        string culture = context.RouteData.Values["culture"]?.ToString();

        if (!string.IsNullOrWhiteSpace(culture))
        {
            logger.LogInformation($"Setting the culture from the URL: {culture}");

#if DNX46
            System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);
            System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
#else
            CultureInfo.CurrentCulture = new CultureInfo(culture);
            CultureInfo.CurrentUICulture = new CultureInfo(culture);
#endif
        }

        base.OnActionExecuting(context);
    }
}

На контроллере я используюLanguageActionFilter.

[ServiceFilter(typeof(LanguageActionFilter))]
[Route("api/{culture}/[controller]")]
public class ProductsController : Controller
{
    ...
}

Пока это работает, но у меня есть две проблемы:

Мне не нравится заявлять{culture} на каждом контроллере, так как он мне понадобится на каждом маршруте.У меня культура по умолчанию не работает с этим подходом, даже если я объявил его как[Route("api/{culture=en-US}/[controller]")] по понятным причинам.

Установка результатов маршрута по умолчанию тоже не работает.

app.UseMvc( routes =>
{
    routes.MapRoute(
        name: "DefaultRoute",
        template: "api/{culture=en-US}/{controller}"
    );
});

Я также исследовал в обычаеIRequestCultureProvider реализация и добавить его вUseRequestLocalization метод как

app.UseRequestLocalization(new RequestLocalizationOptions
{
    RequestCultureProviders = new List<IRequestCultureProvider>
    {
        new UrlCultureProvider()
    },
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("de-de"),
        new CultureInfo("en-us"),
        new CultureInfo("en-gb")
    },
    SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("de-de"),
        new CultureInfo("en-us"),
        new CultureInfo("en-gb")
    }
}, new RequestCulture("en-US"));

но тогда у меня нет доступа к маршрутам там (я предполагаю, потому что маршруты сделаны позже в конвейере). Конечно, я также мог бы попытаться разобрать запрошенный URL. И я даже не знаю, смогу ли я изменить маршрут в этом месте, чтобы он соответствовал вышеуказанному маршруту с культурой в нем.

Передача культуры через параметр запроса или изменение порядка параметров внутри маршрута не является вариантом.

Оба URLapi/en-us/products как мыapi/products следует направить на тот же контроллер, где первый не меняет культуру.

Порядок, в котором будет определяться культура, должен быть

Если определено в URL, возьмите егоЕсли не определено в URL, проверьте строку запроса и используйте этоЕсли не определено в запросе, проверьте кукиЕсли не определено в cookie, используйтеAccept-Language заголовок.

2-4 делается черезUseRequestLocalization и это работает. Также мне не нравится текущий подход к добавлению двух атрибутов к каждому контроллеру ({culture} в пути и[ServiceFilter(typeof(LanguageActionFilter))]).

Редактировать: Я также хотел бы ограничить количество допустимых локалей одним набором вSupportedCultures собственностьRequestLocalizationOptions перешел кUseRequestLocalization.

IOptions<RequestLocalizationOptions> localizationOptions вLanguageActionFilter выше не работает, так как возвращает новый экземплярRequestLocalizationOptions гдеSupportedCultures всегдаnull и не тот, который передан.

FWIW это RESTful проект WebApi.

Ответы на вопрос(1)

Ваш ответ на вопрос