MVC3全球化:在模型绑定之前需要全局过滤

Zru*_*uty 14 c# globalization asp.net-mvc asp.net-mvc-3

目前,我有一个全局过滤器GlobalizationFilter,用于检查路由值,cookie和浏览器语言标头,以确定请求的正确文化设置:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    // determine cultureInfo
    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;
}
Run Code Online (Sandbox Code Playgroud)

这一切都有效,但模型绑定过程似乎发生在全局过滤器之前,因此模型绑定器不会考虑文化设置.

这导致解释双值,DateTime值等的问题.

我可以将文化检测代码移到其他位置,但我不喜欢我的任何选择:

  • 应用程序的BeginRequest事件.此时路由尚未发生,因此我将不得不/en-US/从URL 手动取出文化令牌.这是不可接受的.

  • 控制器的Initialize()方法.这将迫使我为所有控制器编写基类,并从中继承现有的控制器.我不喜欢这个,但如果没有更好的结果,我会选择这个解决方案.

理想情况下,我想找到一些方法在"路由完成"和"模型绑定开始"事件之间注入我的代码,但我在MSDN/Google上没有发现任何内容.

或者也许还有其他方法可以处理我不知道的MVC3全球化?

在此先感谢任何贡献.

Rus*_*Cam 15

将确定文化的代码提取到单独的组件/类中.然后创建一个ModelBinder派生自派生DefaultModelBinder的人在调用之前设置文化BindModel

public class CultureAwareModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        /* code that determines the culture */
        var cultureInfo = CultureHelper.GetCulture(controllerContext.HttpContext);

        //set current thread culture
        Thread.CurrentThread.CurrentCulture = cultureInfo;
        Thread.CurrentThread.CurrentUICulture = cultureInfo;

        return base.BindModel(controllerContext, bindingContext);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将其注册为应用程序(in Application_Start)

// register our own model binder as the default
ModelBinders.Binders.DefaultBinder = new CultureAwareModelBinder();
Run Code Online (Sandbox Code Playgroud)