如何将模型绑定中使用的所有ValueProviderResult的文化设置为给定值?

Pet*_*nov 6 asp.net-mvc-3

事实证明,MVC的DefaultModelBinder使用不同的文化,以解析值(例如double,DateTime等)POST VS GET请求. 是更多信息.

我看到这是由对象的Culture属性控制的ValueProviderResult,它们是从中返回的IValueProvider.GetValue().

我的问题是:如何全局确保此值始终为CultureInfo.InvariantCulture.

我知道我可以实现自定义值提供程序并以这种方式执行.

我知道我可以实现自定义模型绑定器并以这种方式执行.

我知道我可以在线程中设置文化,但不幸的是,这不是我的选择.

我正在寻找的是一种设置它的方法,以便即使是默认的模型绑定器和现有的值提供者也能够以文化不变的方式解析,而不管线程文化的设置是什么.

Jim*_*iTh 4

据我所知,没有办法符合你的标准。您必须做您知道可以做的事情之一(我认为最合适的方法是自定义值提供者)。

原因:所有默认 ValueProvider 都被硬编码为使用CultureInfo.InvariantCultureCultureInfo.CurrentCulture

具体来说,这是这样FormValueProvider做的方法:

internal FormValueProvider(
            ControllerContext controllerContext,
            IUnvalidatedRequestValues unvalidatedValues
         )
         : base(
              controllerContext.HttpContext.Request.Form, 
              unvalidatedValues.Form,
              CultureInfo.CurrentCulture // <--- Grrr, argh
         ) 
{
}
Run Code Online (Sandbox Code Playgroud)

不会从其他任何地方检索区域性(即,上面的参数不用作默认值,而是作为要使用的一种区域性)。

不同 IValueProvider 的文化

作为参考,以下是每个默认 IValueProvider 的区域性:

  • ChildActionValueProvider:InvariantCulture
  • FormValueProvider:CurrentCulture
  • JsonValueProvider:当前文化
  • RouteDataValueProvider:InvariantCulture
  • QueryStringValueProvider:InvariantCulture
  • HttpFileCollectionValueProvider:InvariantCulture

替换CurrentCultureIValueProvider

替换 并不是一项艰巨的任务FormValueProvider,因为如上所示,它只是调用其基类的 ( NameValueCollectionValueProvider) 构造函数 - 该构造函数将所需的区域性作为参数。

FormValueProvider 的原始实现表面上看起来比实际更难,因为它引用了内部类和接口。但它们并不是用来取代提供者的——它们只是用于单元测试。

你只需要调用基础构造函数(如上所述),传递两个NameValueCollection很容易获取的:Request.Forms和(一个静态方法)Forms的属性。Validation.Unvalidated(Request)并将第三个参数设置为您想要的文化。

FormValueProviderFactory简单。

JsonValueProvider有点复杂 - 基本上你必须将 的源复制JsonValueProviderFactory到一个新类并修改它 - 因为虽然它允许重写GetValueProvider(),但该方法主要由对其他private static方法的调用组成。

编辑(Petar Ivanov):这对我有用。为了使其工作,将自定义工厂添加到 是不够的ValueProviderFactories.Factories,因为这样它是添加在FormValueProviderFactory. 相反,我不得不FormValueProviderFactory用定制的替换它。