使用OWIN和异步方法的多语言网站

Cro*_*zin 12 c# asynchronous internationalization async-await owin

背景

我正在使用IIS上的ASP.NET 4.6,C#,OWIN管道Microsoft.Owin.Host.SystemWeb,大量异步方法调用和标准的全局资源文件(*.resxin App_GlobalResources)创建一个简单的多语言网站.该网站使用MVC5,WebAPI2和Autofac作为依赖性解析器.

问题

我无法正确更改生成的页面的区域设置/文化,因为异步方法每个请求使用多个线程,我找不到Thread.Current[UI]Culture为给定请求关联的每个线程设置的方法,因为这些属性未同步.我还想保持干净的代码,而没有"异步/等待文化配置"搞乱有用的代码.

Startup.cs

public void Configuration(IAppBuilder app)
{
    ...

    app.UseAutofacMiddleware(container);
    app.UseAutofacMvc();
    app.UseAutofacWebApi(httpConfiguration);
    app.UseWebApi(httpConfiguration);

    ...

    app.Use(async (ctx, next) =>
    {
        /* in production, detect based on current URL and/or cookie */
        var culture = new CultureInfo("pl_PL");

        CultureInfo.CurrentCulture = CultureInfo.CurrentUICulture = culture;

        await next.Invoke();
    });
}
Run Code Online (Sandbox Code Playgroud)

SampleController.cs

public async Task<ActionResult> SayHello()
{
    // returns pl_PL message
    var msgA = Resources.Messages.HelloWorld; 

    await someService.doSthAsync();

    // returns system default (en_US) message
    var msgB = Resources.Messages.HelloWorld;

    return Content(msgA + " - " + msgB);
}
Run Code Online (Sandbox Code Playgroud)
  1. 我应该按照此SO答案中的[AspNet]SynchronizationContext建议创建自定义吗?如果是这样的话我应该怎么做?
  2. 我是否应该放弃全球资源作为翻译来源并使用其他方法?如果是这样,我可以使用什么(库?)?

Jul*_*bot 5

如何使用Owing Globalization Library,它似乎就是为此而创建的.

您仍然可以使用您的resx本地化您的资源,它具有很好的自定义功能:

public void Configuration(IAppBuilder app)
{
    ...
    app.UseGlobalization(new OwinGlobalizationOptions("en-US",true)
       .DisablePaths("Content", "bundles")
       .Add("fr-FR", true).AddCustomSeeker(new CultureFromPreferences()));
}
Run Code Online (Sandbox Code Playgroud)

我测试了async/await的使用并保留了文化:

    public async Task<ActionResult> About()
    {
        var msgA = Resources.Resources.About;

        await Task.Delay(1000);

        var msgB = Resources.Resources.About;

        ViewBag.Message = msgA + " - " + msgB;

        return View();
    }
Run Code Online (Sandbox Code Playgroud)

注意:我不是图书馆的作者,我以前碰巧使用过它.


小智 1

Joe Enzmiger 的回答在这里看起来很合适

public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext     controllerContext, CancellationToken cancellationToken)
{
if (controllerContext.Request.Headers.AcceptLanguage != null && 
    controllerContext.Request.Headers.AcceptLanguage.Count > 0)
{
    string language = controllerContext.Request.Headers.AcceptLanguage.First().Value;
    var culture = CultureInfo.CreateSpecificCulture(language);
    HttpContext.Current.Items["Culture"] = culture;
    //Thread.CurrentThread.CurrentCulture = culture;
    //Thread.CurrentThread.CurrentUICulture = culture;
}

base.ExecuteAsync(controllerContext, cancellationToken); 
}
Run Code Online (Sandbox Code Playgroud)

然后,在任何任务中你都需要文化:

var culture = HttpContext.Current != null ? HttpContext.Current.Items["Culture"] as CultureInfo : Thread.CurrentThread.CurrentCulture;
Run Code Online (Sandbox Code Playgroud)

  • 当您抄袭其他用户的答案时,礼貌的做法是*链接*到原始答案 (2认同)