Il posto migliore per impostare CurrentCulture per applicazioni Web ASP.NET MVC multilingue

Per l’applicazione Web ASP.NET MVC 3 multilingue, sto determinando il Thread.CurrentThread.CurrentCulture e il Thread.CurrentThread.CurrentUICulture nel controller factory come segue:

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

Il codice sopra riportato ha quasi un anno ora! Quindi, apro suggerimenti.

E lo registro sul file Global.asax come:

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

Funziona bene ma non sono sicuro che sia la migliore pratica e il posto migliore per fare questo tipo di azione.

Non ho approfondito il ruolo principale di ControllerFactory e non riesco a confrontarlo con ActionFilterAttribute .

Cosa ne pensi del posto migliore per fare questo tipo di azione?

Ho usato un ActionFilter globale per questo, ma recentemente mi sono reso conto che impostare la cultura corrente nel metodo OnActionExecuting è troppo tardi in alcuni casi. Ad esempio, quando il modello dopo la richiesta POST arriva al controller, ASP.NET MVC crea un metadata per il modello. Si verifica prima che qualsiasi azione venga eseguita. Di conseguenza, i valori dell’attributo DisplayName e altri elementi di Annotazioni dati vengono gestiti utilizzando la cultura predefinita a questo punto.

Alla fine ho spostato l’impostazione della cultura corrente sull’implementazione personalizzata di IControllerActivator e funziona come un incantesimo. Suppongo che sia quasi lo stesso dal punto di vista del ciclo di vita delle richieste di ospitare questa logica nel controller personalizzato, come oggi. È molto più affidabile dell’utilizzo di ActionFilter globale.

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

So che un anser è già stato selezionato. L’opzione che abbiamo usato era solo inizializzare la cultura corrente del thread nell’evento OnBeginRequest per l’applicazione. Questo assicura che la cultura venga scoperta ad ogni richiesta

 public void OnBeginRequest(object sender, EventArgs e) { var culture = YourMethodForDiscoveringCulutreUsingCookie(); System.Threading.Thread.CurrentThread.CurrentCulture = culture; System.Threading.Thread.CurrentThread.CurrentUICulture = culture; } 

Un posto alternativo per mettere questo sarebbe mettere quel codice nel metodo OnActionExecuting di un ActionFilter personalizzato, che può essere registrato nella raccolta GlobalFilters:

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

Invece di OnActionExecuting override di OnActionExecuting puoi eseguire l’override di Initialize qui in questo modo

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