在使用 ModelBinder 之前更改文化

Posted

技术标签:

【中文标题】在使用 ModelBinder 之前更改文化【英文标题】:Change culture before ModelBinder is used 【发布时间】:2012-11-18 22:28:49 【问题描述】:

我想创建一个不同语言的网站。我已经读到我可以创建一个ActionFilter,但我有一个小问题: 我必须创建一个自定义 ModelBinder 才能使用英语和德语数字格式(123,456,789.1123.456.789,1

public class DecimalModelBinder : DefaultModelBinder

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    
        string key = bindingContext.ModelName;
        var v = ((string[])bindingContext.ValueProvider.GetValue(key).RawValue)[0];
        float outPut;
        if (float.TryParse(v, NumberStyles.Number, System.Globalization.CultureInfo.CurrentCulture, out outPut))
            return outPut;
        return base.BindModel(controllerContext, bindingContext);

    

此 ModelBinder 使用当前区域性来决定使用哪种格式。 但不幸的是,ModelBinder 是在 ActionFilter 改变文化之前使用的。

如何在 ModelBinder 激活之前更改文化?

【问题讨论】:

【参考方案1】:

您可以实现 IHttpModule 并在 BeginRequest 中设置文化,如 here 所示。

void context_BeginRequest(object sender, EventArgs e)

    // eat the cookie (if any) and set the culture
    if (HttpContext.Current.Request.Cookies["lang"] != null)
    
        HttpCookie cookie = HttpContext.Current.Request.Cookies["lang"];
        string lang = cookie.Value;
        var culture = new System.Globalization.CultureInfo(lang);
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
    

【讨论】:

它工作正常,非常感谢!但是我有一个问题:你知道吗,为什么每次请求都会执行 5 次代码? 我没有这种行为。能不能给((System.Web.HttpApplication)(sender)).Request.RawUrl加个watch看看请求是不是一样? @Christopher 代码在每个请求中执行一次(因此命名为 BeginRequest),因此页面可能有一个请求,样式表、图像或 javascript 文件可能还有 4 个请求。检查 Request.Url,这可能会有所帮助。【参考方案2】:

我通常通过处理Global.asax.cs 中的PreRequestHandlerExecute 事件来设置CurrentCultureCurrentUICulture(您也可以按照barry 的建议在IHttpModule 中处理此事件)。

关键是在模型绑定发生之前发生的事件中执行此操作。在此之前还发生了其他一些事件,您可以利用这些事件。

查看HttpApplication Class 以获取有关可用事件及其引发顺序的信息。

    public class MvcApplication : HttpApplication
    
        protected void Application_PreRequestHandlerExecute(object sender, EventArgs e)
        
            var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;
        
    

您也可以通过处理Controller 上的OnActionExecuting 事件来实现(您可能希望创建一个基本控制器并在那里执行此操作,然后让您的所有控制器都从该基本控制器继承)。

    public class MyBaseController : Controller
    
        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        
            var culture = new CultureInfo("en-GB"); // Get the culture name from the route values / request querystring / form / cookie
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;

            base.OnActionExecuting(filterContext);
        
    

    public class MyController : MyBaseController
    
        public ActionResult Index()
        
            return View();
        
    

【讨论】:

-1:在调用模型绑定器之后调用 OnActionExecuting。所以 OnActionExecuting 为时已晚。【参考方案3】:

IAuthorizationFilter 的实例在模型绑定之前执行,从而允许您设置所需的文化

【讨论】:

以上是关于在使用 ModelBinder 之前更改文化的主要内容,如果未能解决你的问题,请参考以下文章

单击按钮时更改文化(语言)

MVC学习系列——ModelBinder扩展

在不使用代码的情况下更改 Windows 区域设置/文化

ASP .NET Web API ModelBinder单个参数

ModelBinder

如何从自定义 ModelBinder 中的正文获取数据?