6

私のJqueryスクリプトでは.、分数の区切り文字としてを使用するブラウザーのCultureInfo(en-UK)を使用して2つのdoubleを投稿しています。,私のMVCアプリは、分数区切り文字としてを使用して、ロケールnl-BEのサーバーで実行されています。

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult GetGridCell(double longitude, double latitude)
{
    var cell = new GridCellViewModel { X = (int)Math.Round(longitude, 0), Y = (int)Math.Round(latitude, 0) };
    return Json(cell);
}

解析の問題が原因で、モデルバインディングが失敗します。

javascriptをen-UKに設定し、MVCアプリのモデルバインディングでも同じように設定するのが最善だと思います。しかし、私もその方法がわかりません。
助言がありますか?

4

2 に答える 2

8

デフォルトのモデル バインダー (DefaultModelBinder) でローカライズがどこまで進んでいるかはわかりませんが、データのカルチャ固有の解析を処理できるバインダーを自分で簡単に作成できます。たとえば、新しいクラスを作成します。DoubleModelBinder と呼びましょう。以下をコピペします。

public class DoubleModelBinder : IModelBinder
{
    /// <summary>
    /// Binds the value to the model.
    /// </summary>
    /// <param name="controllerContext">The current controller context.</param>
    /// <param name="bindingContext">The binding context.</param>
    /// <returns>The new model.</returns>
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var culture = GetUserCulture(controllerContext);

        string value = bindingContext.ValueProvider
                           .GetValue(bindingContext.ModelName)
                           .ConvertTo(typeof(string)) as string;

        double result = 0;
        double.TryParse(value, NumberStyles.Any, culture, out result);

        return result;
    }

    /// <summary>
    /// Gets the culture used for formatting, based on the user's input language.
    /// </summary>
    /// <param name="context">The controller context.</param>
    /// <returns>An instance of <see cref="CultureInfo" />.</returns>
    public CultureInfo GetUserCulture(ControllerContext context)
    {
        var request = context.HttpContext.Request;
        if (request.UserLanguages == null || request.UserLanguages.Length == 0)
            return CultureInfo.CurrentUICulture;

        return new CultureInfo(request.UserLanguages[0]);
    }
}

ここで行っているのは、独自の言語対応のダブル パーサーを確立することです。IModelBinder インターフェイスを実装するときは、BindModel メソッドを作成する必要があります。ここで処理が行われますが、何かを解析する前に、ブラウザーの言語に基づいて IFormatProvider を取得する必要があります。そのため、GetUserCulture メソッドを使用して、ブラウザーの言語を試して準備します。今の文化に戻らないと。

それができたら、値を解析できます。最初に ValueProvider (実際には Form コレクション、Request コレクションなどの多くの値プロバイダーの複合体) から取得し、次に、発見された IFormatProvider (現在持っている CultureInfo) を使用して解析します。

それが完了したら、それをモデル バインダー コレクションに追加するのは非常に簡単です。

ModelBinder.Binders[typeof(Double)] = new DoubleModelBinder();

それを試して、それが役立つかどうかを確認してください。

于 2010-07-04T18:38:08.207 に答える
1

ModelBinding は CurrentCulture を使用して値を解析します。ユーザーがテキストボックスに日付または小数を入力すると、値が正しく解析されるため、これは理解できます。

しかし、ほとんどの開発者は、ユーザーが使用する言語に関係なく、同じカルチャを使用してすべての値が解析されることを望んでいます。ユーザーの形式で値を表示したいが、中立的な形式 (InvariantCulture) で値を入力したい。

そのため、Application.BeginRequest の CurrentCulture を CultureInfo.InvariantCulture に設定しました。そのため、すべての Binding は不変の Culture を使用します。後で Ressources を使用したり、ブラウザーの言語で値をフォーマットしたりする場合は、CurrentCulture をユーザーの言語に再度設定して、ユーザーの言語に戻す必要があります。これはアクション フィルターで行います。

編集:

OPは、フォームの送信のみが文化を認識しているという点で私を修正しました:それは本当です。文書化されている ValueProviderDictionary:PopulateDictionary のソースを参照してください。

   We use this order of precedence to populate the dictionary:
   1. Request form submission (should be culture-aware)
   2. Values from the RouteData (could be from the typed-in URL or from the route's default values)
   3. URI query string
于 2010-07-04T19:06:31.567 に答える