【问题标题】:Localization works when culture is set via QueryString but not when culture is in route本地化在通过 QueryString 设置文化时有效,但在文化在路线中时无效
【发布时间】:2017-03-01 10:44:39
【问题描述】:

这是我的路线:

        app.UseMvc(routes =>
        {
            routes.MapRoute(
     name: "defaultWithCulture",
     template: "{culture=fa-IR}/{controller}/{action=Index}/{id?}");
        });

但是当我使用链接时本地化工作:

http://localhost:1776/fa-IR/Home/About?culture=fa-ir

但不是什么时候

http://localhost:1776/fa-IR/Home/About

为什么路线中的文化不适用?

【问题讨论】:

  • 你的路由模板应该是template: "{culture}/{controller}/{action=Index}/{id?}");。您如何使用作为 URL 一部分的值来设置当前线程的文化?
  • @ChetanRanpariya 我没有设置它。路由不应该自己做吗?
  • 您想要的行为在 asp.net mvc 核心中没有开箱即用。您可能想要编写一个操作过滤器,该过滤器将从 URL 中检索区域性的路由数据值并将其设置为当前线程。
  • @ChetanRanpariya 您能否将其添加为答案并展示如何操作?
  • 我之前回答过类似的问题。请参考stackoverflow.com/questions/42154050/…如果您在使用这种方法时遇到任何问题,请告诉我。

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


【解决方案1】:

SSA 的回答并没有解决我的问题,但给了我一个很大的线索,最后我得到了它的工作。

要做的是:

  1. 正如 SSA 所说,asp.net 核心按顺序具有以下 RequestCultureProviders。将使用第一个非空值。
QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider

所以我们必须改变它们的顺序,并将路由添加到第一个:

services.Configure<RequestLocalizationOptions>(
    options =>
    {
        var supportedCultures = new List<CultureInfo>
        {
           new CultureInfo("en-US"),
           new CultureInfo("fa-IR"),
        };
        options.DefaultRequestCulture = new RequestCulture(culture: "fa-IR", uiCulture: "fa-IR");
        options.SupportedCultures = supportedCultures;
        options.SupportedUICultures = supportedCultures;
        options.RequestCultureProviders.Clear();
        options.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider();
        options.RequestCultureProviders.Insert(1, new QueryStringRequestCultureProvider());
        options.RequestCultureProviders.Insert(2, new CookieRequestCultureProvider());
        options.RequestCultureProviders.Insert(3, new AcceptLanguageHeaderRequestCultureProvider());                    
        services.AddSingleton(options);
    });

2- 当RouteDataRequestCultureProvider 任务执行时,RoutingData 仍然是 null 并且还没有给定值,所以它总是返回 null,所以我像下面这样更改它以使用 Url.Path 而不是 RoutingData:

public class RouteDataRequestCultureProvider : RequestCultureProvider
{

    public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        string culture = null;
        string uiCulture = null;
         uiCulture =  culture = httpContext.Request.Path.Value.Split('/')[1]?.ToString();
        if (culture == null)
        {
            return TaskCache<ProviderCultureResult>.DefaultCompletedTask;
        }
        var providerResultCulture = new ProviderCultureResult(culture, uiCulture);

        return Task.FromResult(providerResultCulture);
    }
} 

【讨论】:

  • 我和你有同样的问题(RoutingData 为空)。这是一个错误吗?
  • @FernandoMondo 不,这不是错误。因为本地化中间件在MVC路由器之前运行,所以还没有解析。
  • @MarkSzabo 我认为这是一种错误或错误实现。因为这是标准的 aspnet 库,它不工作。并感谢您对该主题的出色指导。我将创建自己的 RequestCultureProvider 类。
  • 那么如果RouteDataRequestCultureProvider在路由之后没有被调用,它有什么用呢?我的意思是 - 我可以通过手动解析路径来使用解决方法,但我有复杂的路由规则。
【解决方案2】:

据我所知,asp.net core 按顺序有以下 RequestCultureProviders。将使用第一个非空值。

QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider

您需要添加RouteDataRequestCultureProvider 以支持来自路线数据的文化。

here为例:

public void ConfigureServices(IServiceCollection services)  
{
    // Add framework services.
    services.AddMvc();

    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("en-GB"),
        new CultureInfo("de"),
        new CultureInfo("fr-FR"),
    };

    var options = new RequestLocalizationOptions()
    {
        DefaultRequestCulture = new RequestCulture(culture: "en-GB", uiCulture: "en-GB"),
        SupportedCultures = supportedCultures,
        SupportedUICultures = supportedCultures
    };
    options.RequestCultureProviders = new[] 
    { 
         new RouteDataRequestCultureProvider() { Options = options } 
    };

    services.AddSingleton(options);
}

【讨论】:

  • 我在几个地方看到了这个解决方案,但问题是,对我来说,我收到错误 The type or namespace name 'RouteDataRequestCultureProvider' could not be found (are you missing a using directive or an assembly reference?) 并且我找不到任何可以解决问题的命名空间。你知道我该如何解决吗?
  • 您需要获取 Microsoft.AspNetCore.Localization.Routing 包。 "Microsoft.AspNetCore.Localization.Routing": "1.1.0"
猜你喜欢
  • 2015-01-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-07
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多