6

MVC は、POST 要求と GET 要求の値 ( 、 など) をDefaultModelBinder解析するために異なるカルチャを使用していることが判明しました。ここに詳細があります。doubleDateTime

これは、から返されるオブジェクトのCultureプロパティによって制御されていることがわかります。ValueProviderResultIValueProvider.GetValue()

私の質問は、この値が常に CultureInfo.InvariantCulture であることをグローバルに確認するにはどうすればよいかということです。

カスタム値プロバイダーを実装して、この方法で実行できることはわかっています。

カスタム モデル バインダーを実装して、この方法で実行できることはわかっています。

スレッドでカルチャを設定できることはわかっていますが、残念ながら、これは私の場合のオプションではありません。

私が探しているのは、デフォルトのモデル バインダーと既存の値プロバイダーでさえ、スレッド カルチャの設定に関係なく、カルチャ不変の方法で解析できるように設定する方法です。

4

1 に答える 1

4

私の知る限り、あなたの基準に合う方法はありません。できることわかっていることの 1 つを実行する必要があります (最も適切な方法は、カスタム値プロバイダーだと思います)。

理由: デフォルトの ValueProvider はすべて、 または のいずれCultureInfo.InvariantCultureかを使用するようにハードコードされていますCultureInfo.CurrentCulture

具体的には、次のようFormValueProviderになります。

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

カルチャは他のどこからも取得されません (つまり、上記の引数はデフォルトとして使用されるのではなく、使用する 1 つのカルチャとして使用されます)。

さまざまな IValueProvider のカルチャ

参考までに、これらは既定の IValueProvider ごとのカルチャです。

  • ChildActionValueProvider: InvariantCulture
  • FormValueProvider: CurrentCulture
  • JsonValueProvider: CurrentCulture
  • RouteDataValueProvider: InvariantCulture
  • QueryStringValueProvider: InvariantCulture
  • HttpFileCollectionValueProvider: InvariantCulture

CurrentCultureIValueProviderの置き換え

FormValueProvider上記のように、基本クラスの ( ) コンストラクターを呼び出すだけなので、 を置き換えるのは大した作業ではありませんNameValueCollectionValueProvider。これは、目的のカルチャを引数として受け取ります。

FormValueProvider の元の実装は、内部クラスとインターフェイスへの参照により、実際よりも難しいように見えます。ただし、プロバイダーを置き換えるために必要なわけではありません。単体テストのためにのみ存在します。

NameValueCollection簡単に取得できる 2 つの と(静的メソッド)Request.FormsFormsプロパティを渡して、(前述のように) 基本コンストラクターを呼び出すだけで済みます。Validation.Unvalidated(Request)そして、3 番目の引数を必要なカルチャに設定します。

FormValueProviderFactoryさらに簡単です。

JsonValueProviderはもう少し複雑です。基本的には、 のソースをJsonValueProviderFactory新しいクラスにコピーして変更する必要があります。これは、 のオーバーライドは可能ですがGetValueProvider()、そのメソッドは主に他のメソッドの呼び出しで構成されているprivate staticためです。

編集 (Petar Ivanov):これでうまくいきました。それを機能させるには、カスタム ファクトリを に追加するだけでは十分ではありませんでしValueProviderFactories.FactoriesFormValueProviderFactory。代わりにFormValueProviderFactory、カスタムのものに交換する必要がありました。

于 2013-07-17T21:06:30.180 に答える