Edu Edu - 3 months ago 15
ASP.NET (C#) Question

Avoiding repeating code on API Actions but still supporting multi language

My goal is to create an API that supports multiple languages.

It is working, but only if I call

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);


on each Action, something that I suppose that can be avoided.




On WebApiConfig.cs file I created a route to support multiple languages, placing that language before the default route
"{lang}/api/{controller}/{id}"
. That means that for English I can call
http://localhost/en/api/service/get
and for Portuguese
http://localhost/pt/api/service/get
.

WebApiConfig.cs:

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApiLocalized",
routeTemplate: "{lang}/api/{controller}/{id}",
constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})"}, // en or en-US
defaults: new { id = RouteParameter.Optional }
);

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





On my Action I receive the language and use it to change the Culture.

ServiceController.cs

public class ServiceController : ApiController
{
[HttpGet]
public string Get(string lang)
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);
return Resources.Global.Country;
}
}





When I call
http://localhost/en/api/service/get
or
http://localhost/pt/api/service/get
I get the string in their respective languages, working perfectly.

How can I avoid using

Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(lang);


on all Actions?

Where can I write it once in the code, but still getting the needed
lang
argument?


  • I've tried Global.asax.cs, but I don't know if I can (and how) get that
    lang
    argument.

  • I don't know if I can (and how) put it on WebApiConfig.cs.


Answer

If you are after removing some code from all your action method and want that in a central place to avoid code duplication, you may consider creating an action filter and apply it globally so that it will be applicable to all requests.

public class LangSettingActionFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var routeData= actionContext.Request.GetRouteData();
        object langCode;
        if (routeData.Values.TryGetValue("lang", out langCode))
        {
          //the languageCode from url is in langCode variable. Use it as needed.
          //Thread.CurrentThread.CurrentUICulture =
                                    //CultureInfo.GetCultureInfo(langCode.ToString());

        }
        base.OnActionExecuting(actionContext);
    }
}

You can register this filter globally inside the Register method of your WebApiConfig class.

public static void Register(HttpConfiguration config)
{
   // Your existing route definiton here
   config.Filters.Add(new LangSettingActionFilter());
}
Comments