本文介绍了为多语言 ASP.NET MVC Web 应用程序设置 CurrentCulture 的最佳位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于多语言 ASP.NET MVC 3 Web 应用程序,我确定控制器工厂上的 Thread.CurrentThread.CurrentCultureThread.CurrentThread.CurrentUICulture 如下:

public class MyControllerFactory : DefaultControllerFactory {受保护的覆盖 IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) {//获取RouteData中的{language}参数字符串 UILanguage;if (requestContext.RouteData.Values["language"] == null)UILanguage = "tr";别的UILanguage = requestContext.RouteData.Values["language"].ToString();//获取语言代码的文化信息CultureInfoculture = CultureInfo.CreateSpecificCulture(UILanguage);Thread.CurrentThread.CurrentCulture = 文化;Thread.CurrentThread.CurrentUICulture = 文化;返回 base.GetControllerInstance(requestContext, controllerType);}}

上面的代码已经快一年了!所以,我愿意征求建议.

我在 Global.asax 文件中注册它,例如:

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

这很好用,但我不确定这是否是执行此类操作的最佳实践和最佳位置.

我还没有深入研究 ControllerFactory 的主要作用,也无法将它与 ActionFilterAttribute 进行比较.

您认为执行此类操作的最佳地点是什么?

解决方案

我为此使用了全局 ActionFilter,但最近我意识到,在 OnActionExecuting 中设置当前文化code> 方法在某些情况下为时已晚.例如,当 POST 请求之后的模型到达控制器时,ASP.NET MVC 会为模型创建元数据.它发生在执行任何操作之前.因此,此时 DisplayName 属性值和其他数据注释内容将使用默认区域性进行处理.

最终,我将当前文化的设置转移到了自定义的 IControllerActivator 实现中,它的作用就像一个魅力.我想从请求生命周期的角度来看,在自定义控制器工厂中托管这个逻辑几乎是一样的,就像你今天一样.它比使用全局 ActionFilter 可靠得多.

CultureAwareControllerActivator.cs:

公共类 CultureAwareControllerActivator:IControllerActivator{public IController Create(RequestContext requestContext, Type controllerType){//获取RouteData中的{language}参数字符串语言 = requestContext.RouteData.Values["language"] == null ?"tr" : requestContext.RouteData.Values["language"].ToString();//获取语言代码的文化信息CultureInfo 文化 = CultureInfo.GetCultureInfo(language);Thread.CurrentThread.CurrentCulture = 文化;Thread.CurrentThread.CurrentUICulture = 文化;返回 DependencyResolver.Current.GetService(controllerType) 作为 IController;}}

Global.asax.cs:

公共类 MvcApplication : System.Web.HttpApplication{protected void Application_Start(){...ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactory(new CultureAwareControllerActivator()));}}

For multilingual ASP.NET MVC 3 web application, I am determining the Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture on the controller factory 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);
    }

}

And I register this on the Global.asax file like:

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

This is working good but I am not sure if it is the best practice and best place to do this type of action.

I haven't dug into the main role of ControllerFactory and I am unable to compare it against ActionFilterAttribute.

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

解决方案

I used a global ActionFilter for this, but recently I realized, that setting the current culture in the OnActionExecuting method is too late in some cases. For example, when model after POST request comes to the controller, ASP.NET MVC creates a metadata for model. It occurs before any actions get executed. As a result, DisplayName attribute values, and other Data Annotations stuff are handled using the default culture at this point.

Eventually I've moved setting the current culture to the custom IControllerActivator implementation, and it works like a charm. I suppose it's almost the same from the request lifecycle perspective to host this logic in the custom controller factory, like you have today. It's much more reliable, than usage of 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()));
    }
}

这篇关于为多语言 ASP.NET MVC Web 应用程序设置 CurrentCulture 的最佳位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-22 11:02