asp.net-mvc 为多语言 ASP.NET MVC Web 应用程序设置 CurrentCulture 的最佳位置

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8226514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:36:01  来源:igfitidea点击:

Best place to set CurrentCulture for multilingual ASP.NET MVC web applications

asp.net-mvcasp.net-mvc-3action-filtercontroller-factory

提问by tugberk

For multilingual ASP.NET MVC 3 web application, I am determining the Thread.CurrentThread.CurrentCultureand Thread.CurrentThread.CurrentUICultureon the controller factory as follows:

对于多语言ASP.NET MVC 3 web应用程序,我决定Thread.CurrentThread.CurrentCultureThread.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);
    }

}

The above code is nearly a year old now! So, I open for suggestions.

上面的代码现在快一年了!所以,我愿意征求建议。

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

我将其注册到 Global.asax 文件中,例如:

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 ControllerFactoryand I am unable to compare it against ActionFilterAttribute.

我还没有深入研究 的主要作用,ControllerFactory也无法将其与ActionFilterAttribute.

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

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

回答by s.ermakovich

I used a global ActionFilterfor this, but recently I realized, that setting the current culture in the OnActionExecutingmethod 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, DisplayNameattribute values, and other Data Annotations stuff are handled using the default culture at this point.

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

Eventually I've moved setting the current culture to the custom IControllerActivatorimplementation, 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.

最终,我已经将当前文化设置为自定义IControllerActivator实现,它就像一个魅力。我想从请求生命周期的角度来看,在自定义控制器工厂中托管这个逻辑几乎是一样的,就像今天一样。它比使用 global 更可靠ActionFilter

CultureAwareControllerActivator.cs:

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:

Global.asax.cs:

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

回答by Agile Jedi

I know an anser has already been selected. The option we used was to just Initialize the thread current culture in the OnBeginRequest event for the Application. This ensures the culture is discovered with every request

我知道已经选择了一个分析器。我们使用的选项是在应用程序的 OnBeginRequest 事件中初始化线程当前区域性。这确保了每个请求都能发现文化

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

回答by Paul Stovell

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

另一个放置它的地方是将该代码放在自定义 ActionFilter 的 OnActionExecuting 方法中,该方法可以在 GlobalFilters 集合中注册:

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

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

回答by Hitendra

Instead of overriding OnActionExecutingyou can override Initializehere like this

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

回答by Delyan

If you don't use ControllerActivator, can use BaseController class and inhеrid from it.

如果不使用 ControllerActivator,可以使用 BaseController 类并继承它。

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


public class HomeController: BaseController    
{
    [HttpGet]
    public ActionResult Index()
    {
        //..............................................
    }
}