11

MVC3 ソリューションを MVC4 にアップグレードしました。移行後、バリデータは壊れています。

言語としてドイツ語を選択した場合、入力日は「20.03.2013」です。MVC4 では検証エラーが発生しますが、MVC3 では発生しません。形式を「20.03.2013」から「20/03/2013」に置き換えると、MVC4 では機能しますが、MVC3 では機能しません;-)

現在のスレッドの UI カルチャをドイツ語に設定しました。ResX 値の出力は正しい言語であるため、カルチャにエラーはないはずです。、サイト自体のみ。エラー メッセージは英語ですが、サイトはドイツ語です。

これは、バリデーターが間違った UI カルチャを使用していることを意味すると思います。

これが私が使用するコードです。

[必須 (ErrorMessageResourceName = "Error_DepartureDate", ErrorMessageResourceType = typeof(Resx.Query))]
公開日時? 出発日{取得; 設定; }

レンダリングされた html がきれいに見えるので、デフォルトのモデル バインダーに何か問題があると思います。

data-lang="de" data-mindate="3" data-val="true" data-val-required="Bitte geben Sie das gewünschte Reisedatum des Hinflugs ein." id="出発日" name="出発日" tabindex="3" type="text" value="" 

Visual Studio 2012 (SP1 がインストールされている) テンプレートを使用して新しい Mvc アプリケーションを作成するときに出荷されるソースに Jscript をアップグレードしました。これは影響がありませんでした。

セッションから現在のカルチャを読み取り、小さなヘルパー関数を使用してカルチャを設定する CultureModelBinder があります。

public static void UpdateThreadCulture(CultureInfo カルチャー)
{
  Thread.CurrentThread.CurrentUICulture = 文化;            
}        

カルチャ モデル バインダーは、既定のバインダーです。

ModelBinders.Binders.DefaultBinder = new CultureModelBinder();
ModelBinders.Binders.Add(typeof(DateTime?), new DateTimeModelBinder());
// そして、さらに多くの

mvc4 で実行順序が変更されて問題が発生した可能性がありますか?

更新: プロジェクトは、.NET Framework 4.5 をターゲットとして使用します。

更新 2:

ユーザーが16の異なる言語を選択できるコンボボックスがあり、それぞれに固有のフォーマットがあります。

例: DE-de -> DD.MM.YYYY; en-en -> DD/MM/YYYY; en-us -> MM/DD/YYYY

現在の文化を設定することについてのヒントを得たところです。これがそのまま正しいはずであるという証拠です。このコードは、バリデータが失敗したときにヒットしません。クライアント側で発生したようです。

   パブリック クラス DateTimeModelBinder : IModelBinder
    {
        プライベート LogService _log = 新しい LogService();

        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {            
            オブジェクトの結果 = null;
            ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
            if (valueResult != null)
            {
                試す
                {
                    var stateHandler = new StateHandler(controllerContext.HttpContext.Session);                    
                    結果 = valueResult.ConvertTo(typeof(DateTime?), stateHandler.Culture);                                       
                }
                キャッチ
                {
                    試す
                    {
                        結果 = valueResult.ConvertTo(typeof(DateTime?), CultureInfo.InvariantCulture);
                    }
                    キャッチ(例外例)
                    {
                        _log.Error("DateTimeModelBinder 解析例外", ex);
                        _log.KeyValue("AttemptedValue", valueResult.AttemptedValue);                                           
                    }                    
                }
            }
            結果を返します。
        }
    }

完全を期すために、私のカルチャモデルバインダー:

  public class CultureModelBinder : DefaultModelBinder
    {      
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            StateHandler stateHandler = new StateHandler(controllerContext.HttpContext.Session);
            Helper.UpdateThreadCulture(stateHandler.Culture);

            base.BindModel(controllerContext, bindingContext); を返します。
        }        
    }

更新: おそらく、この問題との相関関係があります: http://connect.microsoft.com/VisualStudio/feedback/details/705643/a-data-val-date-attribute-is-generated-for-time-fields-in -asp-net-mvc-4

更新: 次の記事を参照してください: http://weblogs.asp.net/scottgu/archive/2010/06/10/jquery-globalization-plugin-from-microsoft.aspx

次のことを試しました:

次の順序でスクリプトをロードしました。

/Scripts/jquery-1.8.3.min.js
/スクリプト/globalize.js
/Scripts/cultures/globalize.cultures.js
// その他の多くのスクリプト...

コールを追加しました。出力は正しく「DE」でした。

        var currentLanguage = $("#DepartureDate").attr("data-lang");
        アラート (現在の言語);       
        $.preferCulture(currentLanguage);

バリデーターへの影響はありません...

4

5 に答える 5

10

重要なのは、Mvc3がポイントであるクライアント側のすべての日付で検証するわけではないということです。サーバー側でカルチャを設定するだけですが、カルチャ設定はクライアント側にはまったく反映されません...少なくともMvcエンジンは自動的にそれを行いません。英語とは異なるカルチャを持つクライアント側で日付と数値を適切に処理する唯一の方法は、すべてのカルチャで日付を適切に解析できるjavascriptグローバリゼーションライブラリを使用し、クライアント側のカルチャをサーバー側のカルチャと等しく設定することです。 、次に、グローバル化された関数を使用するには、すべての検証メソッドを適切に再定義する必要があります。クライアント側でグローバリゼーションを適切に処理する方法を明確にした私のブログのこの投稿を読んでください。http://www.dotnet-programming.com/post/2011/12/14/Globalization-Validation-and-DateNumber-Formats-in-AspNet-MVC.aspx

さらに、CurrentCultureとCurrentUICultureを混同しないでください。CurrentUICultureは、数値や日付の処理方法にはまったく影響しませんが、ローカライズされた文字列などのカルチャ固有のリソースを含むリソースファイルにのみ影響します。

最後に、モデルバインダーは再帰関数であり、モデルの再構築中に何百回も呼び出されるため、モデルバインダーにカルチャを設定することは非常に非効率的です。また、カルチャ設定操作は単純な変数設定操作ではありませんが、無視できないコスト。カルチャ設定を処理するグローバルコントローラーフィルターを作成することをお勧めします(私は常にこのようにします)。これにより、操作はリクエストごとに1回だけ実行されます。

于 2012-12-02T15:08:53.767 に答える
3

デフォルトの日付バリデータを上書きしてみてください:

// Replace dots so jq validator can understand what's going on
$(function () {
    $.validator.addMethod(
    "date",
    function (value, element) {
        var s = value;
        s = value.replace(/\./g, '/');

        // Chrome requires tolocaledatestring conversion, otherwise just use the slashed format
        var d = new Date();
        return this.optional(element) || !/Invalid|NaN/.test(new Date(d.toLocaleDateString(value))) || !/Invalid|NaN/.test(new Date(s));
    },
    ""
    );
});

$.validator.unobtrusive.parse();
于 2012-11-29T11:39:37.280 に答える
2

ILSpy を使用してコードを調べると、新しく導入された ClientDataTypeModelValidatorProvider が data-val-date 属性を追加しているように見えます。

MVC3 スタイルの機能に戻したい場合は、そのプロバイダーをモデル検証プロバイダーのリストから削除するだけでうまくいきます。

問題は解決しませんが、数行のコードで、jquery 検証のグローバリゼーションの欠如によって引き起こされる問題を取り除くことができます。

using System.Web.Mvc;

...

protected void Application_Start()
{
  var providers = ModelValidatorProviders.Providers;
  var clientDataTypeModelValidatorProvider = providers.OfType<ClientDataTypeModelValidatorProvider>().FirstOrDefault();
  if ( clientDataTypeModelValidatorProvider != null )
  {
    providers.Remove( clientDataTypeModelValidatorProvider );
  }

  ...
}
于 2013-10-01T22:18:19.203 に答える
0

これが Chrome でのみ発生する場合は、日付の検証にカルチャ バグがある jquery バージョンが原因です。

于 2012-12-06T12:48:22.000 に答える
0

Microsoft は、mvc4 の新しい jquery.validate.js を MVC3 プロジェクト テンプレートの古い jquery.validate.js に置き換えることを提案しています。これは機能しますが、面白いことに、バグは MVC4 ではなく、MVC3 にありました。

フランチェスコによって説明された方法を使用します。受け入れられた回答を参照してください。

于 2012-12-05T08:46:34.937 に答える