2011-06-17 26 views
5

私のViewModelにDateTime MyDateのプロパティがあります。ASP.NET MVC 3で特定の形式の日付を検証する

[DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] 
[RegularExpression(@"^(([0-2]\d|[3][0-1])\.([0]\d|[1][0-2])\.[2][0]\d{2})$", 
    ErrorMessage="Failed...")] 
public DateTime MyDate { get; set; } 

ためのコントローラアクション署名HttpPostは、次のようになります。私は、次の属性をユーザーのみ(DD.MM.YYYY)特定の形式のテキストボックス内の日付部分に入ることを確認するとみましたこの:

  1. @Html.TextBoxFor(model => model.MyDate)

  2. :レイザービューで

    [HttpPost] 
    public ActionResult Edit(int id, MyViewModel viewModel) 
    { 
        // MyViewModel contains the MyDate property ... 
        // ... 
        if (ModelState.IsValid) 
        { 
         // ... 
        } 
        // ... 
    } 
    

    は、私は、次の2つの方法を試してみました

  3. @Html.EditorFor(model => model.MyDate)

私が望むように、それは動作しません。結果は次のとおりです。

  • サーバー側の検証は常に両方のヘルパーのために失敗した両方のHTMLヘルパーで期待通り

    • クライアント側の検証でも、正規表現を渡す「2011年6月17日」のような有効な日付で、動作します。 MyDateプロパティは、入力された日付であるviewModelに正しく入力され、アクションに渡されます。モデル結合が機能していたようです。
    • DisplayFormatの属性は、EditorForでのみ尊重されますが、TextBoxForでは拒否されません。 TextBoxForディスプレイ "DD.MM.YYYY HH:mm:ssの"

    質問:

    1. は私がstringない性質上、全くRegularExpressionAttributeを適用することはできますか?もし許可されていれば、サーバ側でDateTimeのような文字列以外のプロパティに対してreg exがどのように評価されますか? reg exと比較してMyDate.ToString()のようなものですか? (これは、ToStringメソッドは、正規表現を渡しません時刻部分を含む文字列を返しますので、検証が失敗したことを説明するだろう。)

    2. は、一般的にのみTextBoxForによってEditorFor、決してによって尊敬DisplayFormat属性ですか?

    3. どのように日付検証の権利を行うことができますか?

  • 答えて

    4

    私は今RegularExpressionを捨てました。タイプDateTimeのプロパティには適していないようです。それから私は、日時やNULL可能のDateTimeのための新しい検証属性を作成しました:

    [AttributeUsage(AttributeTargets.Property, Inherited = false, 
        AllowMultiple = false)] 
    public sealed class DateOnlyAttribute : ValidationAttribute 
    { 
        public DateOnlyAttribute() : 
         base("\"{0}\" must be a date without time portion.") 
        { 
        } 
    
        public override bool IsValid(object value) 
        { 
         if (value != null) 
         { 
          if (value.GetType() == typeof(DateTime)) 
          { 
           DateTime dateTime = (DateTime)value; 
           return dateTime.TimeOfDay == TimeSpan.Zero; 
          } 
          else if (value.GetType() == typeof(Nullable<DateTime>)) 
          { 
           DateTime? dateTime = (DateTime?)value; 
           return !dateTime.HasValue 
            || dateTime.Value.TimeOfDay == TimeSpan.Zero; 
          } 
         } 
         return true; 
        } 
    
        public override string FormatErrorMessage(string name) 
        { 
         return string.Format(CultureInfo.CurrentCulture, 
          ErrorMessageString, name); 
        } 
    } 
    

    は使用方法:

    [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode=true)] 
    [DateOnly] 
    public DateTime MyDate { get; set; } 
    

    これは、クライアント側の検証を提供していません。サーバー側では、モデルバインディング(入力された文字列がDateTimeに変換可能であることを確認するため)に基づいて検証が行われます。ユーザが真夜中以外の時刻パートを入力した場合、DateOnlyアトリビュートがキックインし、日付のみを入力するよう警告が表示されます。

    10

    日付を検証するために正規表現を使用しないでください。これらは単に無視されます。

    文化の相違が問題の根本原因かもしれません。クライアント側の検証では、ブラウザのカルチャを使用して日付を検証します。たとえば、en-USに設定されている場合、予想される形式はMM/dd/yyyyになります。サーバーがfr-FRを使用するように構成されている場合、予期される形式はdd/MM/yyyyになります。

    web.configの<globalization>要素を使用して、サーバー側のカルチャを設定できます。あなたはそれがクライアントと同じ文化を使用して、このような方法でそれを設定することができます:

    <globalization culture="auto" uiCulture="auto"/> 
    

    Hanselman氏は、ASP.NET MVCでのグローバリゼーションとローカリゼーションについてnice blog postを持っています。

    +0

    リンクをありがとうございます。今後の参考に利用できるようブックマークしました。しかし、私の問題はローカリゼーションとは関係ないと思います。私は正規表現が無視されているとは思わない:クライアント側の検証が動作し、サーバ側の検証もreg exで何かをする(ModelStateが言うように、このreg exに対して失敗する)。私はdevマシン(クライアントとサーバー=同じマシン)でテストしているので、ロケールは同じです。しかし、私はまた、reg exを使うのは間違っていると信じています(無視されません)。ユーザーが時間のない部分に日付を入力するだけであることをどのように検証しますか? – Slauma

    +1

    @Slauma、これを同じマシンで試したという事実は、ブラウザとサーバーのカルチャ設定に違いがないことを意味するものではありません。時間の部分については、日付を入力する必要がある形式をユーザーに伝えるだけで、サーバー上ではアプリケーションに必要がない場合は時間部分を無視します。おそらくjqueryの日付ピッカーを提供して、ユーザーが日付を正しい形式で入力するのを簡単にするかもしれません。 –

    +0

    あなたは正しいです、私はあまりにも複雑にしようとしています。今のところ、ユーザー入力のためのもう少しの助けとして、私は 'DateOnly'属性を作成しました(私自身の答えを見てください)。日付ピッカーは、ユーザーのためのより良いヘルプです!私は次のステップの1つとしてそれを試みます。 – Slauma

    関連する問題