【问题标题】:Best place to set CurrentCulture for multilingual ASP.NET WebAPI applications为多语言 ASP.NET WebAPI 应用程序设置 CurrentCulture 的最佳位置
【发布时间】:2014-03-19 12:17:05
【问题描述】:

基于这个问题 (Best place to set CurrentCulture for multilingual ASP.NET MVC web applications),我正在寻找一种全局方法来为 ASP.NET WebAPI 做同样的事情。

我当前的 ASP.NET MVC 实现如下所示:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);


        ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CultureAwareControllerActivator()));


    }
}


public class CultureAwareControllerActivator : System.Web.Mvc.IControllerActivator
{
    public System.Web.Mvc.IController Create(System.Web.Routing.RequestContext requestContext, System.Type controllerType)
    {
        string cultureName = null;

        // Attempt to read the culture cookie from Request
        HttpCookie cultureCookie = requestContext.HttpContext.Request.Cookies["_culture"];
        if (cultureCookie != null)
            cultureName = cultureCookie.Value;
        else
            cultureName = requestContext.HttpContext.Request.UserLanguages != null && requestContext.HttpContext.Request.UserLanguages.Length > 0 ?
                      requestContext.HttpContext.Request.UserLanguages[0] :  // obtain it from HTTP header AcceptLanguages
                      null;

        // Validate culture name
        cultureName = RoedingGmbh.Pis2Go.Web.Mvc.Helpers.CultureHelper.GetImplementedCulture(cultureName); // This is safe

        // Modify current thread's cultures            
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureName);
        // Currently the UI Language is only english
        //Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;

        return DependencyResolver.Current.GetService(controllerType) as IController;
    }
}

我正在尝试执行与 ASP.NET MVC 中相同的操作,但以下代码无法正常工作。

 public static class WebApiConfig
 {
      public static void Register(HttpConfiguration config)
      {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                 name: "DefaultApi",
                 routeTemplate: "api/{controller}/{id}",
                 defaults: new { id = RouteParameter.Optional }
            );

            GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Dispatcher.IHttpControllerActivator), new CultureAwareHttpControllerActivator());

          }
 }


 public class CultureAwareHttpControllerActivator : System.Web.Http.Dispatcher.IHttpControllerActivator
 {
     public System.Web.Http.Controllers.IHttpController Create(System.Net.Http.HttpRequestMessage request, System.Web.Http.Controllers.HttpControllerDescriptor controllerDescriptor, Type controllerType)
     {
        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("DE-de");
        return GlobalConfiguration.Configuration.DependencyResolver.GetService(controllerType) as System.Web.Http.Controllers.IHttpController;
     }
 }

使用该代码,WebAPI 无法再找到任何路由 :( 我该怎么做才能让它发挥作用!

问候, 丹尼尔

【问题讨论】:

    标签: asp.net globalization asp.net-web-api


    【解决方案1】:

    如果您想要整个应用程序的全局本地化,您可以将设置的文化代码放入全局asax文件中HttpApplication的BeginRequest方法中。这会将您的文化设置在 每个 请求的最前面,并将影响每个 MVC 和 webapi 请求。

    【讨论】:

    • 你的答案似乎很简单,但它就像一个魅力。感谢您的快速回答!
    • 但是使用 await/async 的线程呢?这会通过它们传播吗?
    • 如果需要 User.Identity,最好使用 AuthenticateRequest,因为在 BeginRequest 上尚未定义用户。旁注:我无法设置事件处理程序。这个帖子帮助了我:stackoverflow.com/questions/1123741/…
    • 对于 async/await 和自 .Net Fx4.6,我们应该设置 CultureInfo.CurrentCulture/CurrentUICulture 代替。他们都获得了一个 setter,并且设置它们应该可以跨 async/await 调用工作。但我无法让它在我的情况下工作。我将它们设置在两个异步调用之间的动作过滤器的 ActionExecuting 处理程序中。控制器操作确实看到了变化。
    • 根据answer to a related question,我们必须更早地进行切换,就像在授权过滤器中一样。真是一团糟。
    【解决方案2】:

    我会使用 ActionFilter

    如果您使用的是 Asp.Net MVC

    //A foreigner, has possibly brew a cookie for me
    public class SpeakNativeTongueAttribute : ActionFilterAttribute, IActionFilter
    {
        const string cookieName = "culture";
    
         void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
        {
            var cookieKeys = filterContext.RequestContext.HttpContext.Request.Cookies.AllKeys;
    
            if (cookieKeys.Contains(cookieName))
            {
                //eat the cookie
                var theCultureCookie = filterContext.RequestContext.HttpContext.Request.Cookies[cookieName];
                var theCulture = theCultureCookie.Value;
    
                //say thanks in native tongue
                System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo(theCulture);
                System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.GetCultureInfo(theCulture);
            }
            else
            {
                //Didn't receive a cookie, don't speak their language, those bastards!
    
            }
        }
    }
    

    在 Javascript 中,您可以在名为“culture”的 cookie 中设置语言

    【讨论】:

    • //一个老外,可能给我做了个饼干?
    • 我们一开始是这样做的,但似乎Model Binder在动作过滤器之前被调用,所以你可能会遇到解析问题。全球 asax 最好。
    猜你喜欢
    • 2012-01-03
    • 2011-03-17
    • 2011-08-10
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    相关资源
    最近更新 更多