6

事实证明,MVCDefaultModelBinder使用不同的文化来解析POST 和 GET 请求的值(例如 、 等) double这里有更多信息。DateTime

我看到这是由对象的Culture属性控制的ValueProviderResult,这些对象是从IValueProvider.GetValue().

我的问题是:如何在全球范围内确保该值始终为 CultureInfo.InvariantCulture。

我知道我可以实现自定义值提供程序并这样做。

我知道我可以实现自定义模型绑定器并这样做。

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

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

4

1 回答 1

4

据我所知,没有办法符合您的标准。您不得不做一件您知道可以做的事情(我想说最合适的方法是自定义价值提供者)。

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

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

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

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

不同 IValueProvider 的文化

作为参考,这些是每个默认 IValueProviders 的文化:

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

替换CurrentCultureIValueProviders

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

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

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

FormValueProviderFactory更直接。

JsonValueProvider涉及更多 - 基本上你必须将源复制JsonValueProviderFactory到一个新类并修改它 - 因为虽然它允许覆盖GetValueProvider(),但该方法主要包括对其他private static方法的调用。

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

于 2013-07-17T21:06:30.180 回答