Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best place to set CurrentCulture for multilingual ASP.NET WebAPI applications

based on this question (Best place to set CurrentCulture for multilingual ASP.NET MVC web applications) I'm looking for a global way to do the same for ASP.NET WebAPI.

My current implementation for ASP.NET MVC looks like this:

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;
    }
}

I'm trying to do the same things as in ASP.NET MVC, but following code doesn't work properly.

 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;
     }
 }

With that code, WebAPI cannot find any route anymore :( What have I to do to get this to work!

Regards, Daniel

like image 346
Daniel C. Avatar asked Mar 19 '14 12:03

Daniel C.


2 Answers

If you want global localization for whole application, you can put the set culture code into the BeginRequest method of the HttpApplication in global asax file. This will set your culture in the most first place of each request and will affect every MVC and webapi request.

like image 118
Aik Avatar answered Oct 21 '22 03:10

Aik


I'd use a ActionFilter

If you are using 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!

        }
    }
}

In Javascript you can set the language in a cookie named "culture"

like image 40
NicoJuicy Avatar answered Oct 21 '22 03:10

NicoJuicy