为多语言ASP.NET MVC Web应用程序设置CurrentCulture的最佳位置
对于多语言ASP.NET MVC 3 Web应用程序,我正在确定控制器工厂的Thread.CurrentThread.CurrentCulture
和Thread.CurrentThread.CurrentUICulture
,如下所示:
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); } }
上面的代码现在已经快一年了! 所以,我打开build议。
我注册这个Global.asax文件,如:
ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());
这是行之有效的,但我不确定是否是这种行为的最佳实践和最佳地点。
我没有深入到ControllerFactory
的主要angular色,我无法将其与ActionFilterAttribute
进行比较。
你认为做这种行动的最佳地点是什么?
我为此使用了一个全局ActionFilter
,但是最近我意识到,在OnActionExecuting
方法中设置当前文化在某些情况下已经太晚了。 例如,当POST请求后的模型进入控制器时,ASP.NET MVC为模型创build一个元数据。 它发生在执行任何操作之前。 因此, DisplayName
属性值和其他数据注解的东西在此处使用默认文化处理。
最后,我已经将目前的文化转移到了自定义的IControllerActivator
实现上,它的function就像一个魅力。 我想,从请求生命周期的angular度来看,在自定义控制器工厂中托pipe这个逻辑几乎是一样的,就像今天一样。 比使用全球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())); } }
我知道anser已经被选中了。 我们使用的选项只是初始化应用程序的OnBeginRequest事件中的线程当前文化。 这确保了每一个请求都能发现文化
public void OnBeginRequest(object sender, EventArgs e) { var culture = YourMethodForDiscoveringCulutreUsingCookie(); System.Threading.Thread.CurrentThread.CurrentCulture = culture; System.Threading.Thread.CurrentThread.CurrentUICulture = culture; }
一个替代的地方是把这个代码放在一个自定义ActionFilter的OnActionExecuting方法中,该方法可以在GlobalFilters集合中注册:
http://weblogs.asp.net/gunnarpeipman/archive/2010/08/15/asp-net-mvc-3-global-action-filters.aspx
而不是重写OnActionExecuting
你可以像这样覆盖Initialize
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); }