Best Place to Install CurrentCulture for ASP.NET MVC Multilingual Web Applications

For a multilingual ASP.NET MVC 3 web application, I define Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture on the factory controller as follows:

 public class MyControllerFactory : DefaultControllerFactory { protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) { //Get the {language} parameter in the RouteData string UILanguage; if (requestContext.RouteData.Values["language"] == null) UILanguage = "tr"; else UILanguage = requestContext.RouteData.Values["language"].ToString(); //Get the culture info of the language code CultureInfo culture = CultureInfo.CreateSpecificCulture(UILanguage); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; return base.GetControllerInstance(requestContext, controllerType); } } 

The code above has been around for almost a year! So, I open for suggestions.

And I will register this in the Global.asax file, for example:

 ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory()); 

This works well, but I'm not sure if this is the best practice and the best place for this type of action.

I did not break into the main role of ControllerFactory , and I cannot compare it to ActionFilterAttribute .

What do you think of the best place for this type of action?

+40
asp.net-mvc asp.net-mvc-3 action-filter
Nov 22 '11 at 12:05
source share
5 answers

I used the global ActionFilter to do this, but recently I realized that setting the current culture in the OnActionExecuting method OnActionExecuting in some cases too late. For example, when a model arrives at a controller after a POST request, ASP.NET MVC creates metadata for the model. This happens before any actions are performed. As a result, the DisplayName attribute values ​​and other data annotation data are processed using the default culture at this point.

In the end, I moved the setting of the current culture to the custom implementation of IControllerActivator , and it works like a charm. I believe this is almost the same in terms of the request life cycle for placing this logic in the factory user controller, as it is today. This is much more reliable than using the global ActionFilter .

CultureAwareControllerActivator.cs

 public class CultureAwareControllerActivator: IControllerActivator { public IController Create(RequestContext requestContext, Type controllerType) { //Get the {language} parameter in the RouteData string language = requestContext.RouteData.Values["language"] == null ? "tr" : requestContext.RouteData.Values["language"].ToString(); //Get the culture info of the language code CultureInfo culture = CultureInfo.GetCultureInfo(language); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture; return DependencyResolver.Current.GetService(controllerType) as IController; } } 

Global.asax.cs

 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { ... ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CultureAwareControllerActivator())); } } 
+56
Jun 16 '12 at 15:35
source share

I know that anser is already selected. The option we used is to simply initialize the current thread culture in the OnBeginRequest event for the application. This provides culture detection with every request.

 public void OnBeginRequest(object sender, EventArgs e) { var culture = YourMethodForDiscoveringCulutreUsingCookie(); System.Threading.Thread.CurrentThread.CurrentCulture = culture; System.Threading.Thread.CurrentThread.CurrentUICulture = culture; } 
+7
Nov 20 '14 at 16:40
source share

An alternative place for this would be to put this code in the OnActionExecuting method of a custom ActionFilter that can be registered in the GlobalFilters collection:

http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx

+4
Nov 22 '11 at 12:19
source share

Instead of overriding OnActionExecuting here, you can override Initialize as follows

 protected override void Initialize(RequestContext requestContext) { string culture = null; var request = requestContext.HttpContext.Request; string cultureName = null; // Attempt to read the culture cookie from Request HttpCookie cultureCookie = request.Cookies["_culture"]; if (cultureCookie != null) cultureName = cultureCookie.Value; else cultureName = request.UserLanguages[0]; // obtain it from HTTP header AcceptLanguages // Validate culture name cultureName = CultureHelper.GetValidCulture(cultureName); // This is safe if (request.QueryString.AllKeys.Contains("culture")) { culture = request.QueryString["culture"]; } else { culture = cultureName; } Uitlity.CurrentUICulture = culture; base.Initialize(requestContext); } 
+3
Aug 6 '13 at 5:13
source share

If you are not using ControllerActivator, you can use the BaseController class and inhrid from it.

 public class BaseController : Controller { public BaseController() { //Set CurrentCulture and CurrentUICulture of the thread } } 



 public class HomeController: BaseController { [HttpGet] public ActionResult Index() { //.............................................. } } 
0
Apr 17 '19 at 14:17
source share



All Articles