2010-11-30 23 views
1

ここで簡単な検証が(私は電話番号、郵便番号と同様に検証するためにそれを使用する)私は数文字列だけを強制するために書いた属性の:ValidationAttributeの値常にnull

public class NumericAttribute : ValidationAttribute { 

    public NumericAttribute() { 
     ErrorMessage = SharedModelResources.ValidationStrings.Numeric; // Message coming from a .resx file 
    } 

    public override bool IsValid(object value) { 

     string stringValue = value as string; 

     if (stringValue.IsNotNull()) 
      foreach (var c in stringValue) 
       if (!char.IsDigit(c)) 
        return false; 

     return true; 
    } 

} 

問題は、使用時に検証することです文字列以外の10進数、短い文字、intなど何もかも、object valueは常にnullです。なぜ数字のみの小数を検証するのですか?私がしなければ、デフォルトの検証メッセージ '値' x 'は' propertyName 'には無効です。私は、デフォルトの検証メッセージの特定の問題に対する解決策を認識しています。

私はちょうどそれは常にnullだ理由を理解したい

...

ところで、私は、ASP.NET MVC 2(最終)VS2008、.NET 3.5 SP1を使用しています。

答えて

1

[OK]をクリックして、検証属性にデバッグを完全にダウン(View> Controller> Model)してください。

はここで何が起こったのです:モデル内の文字列ではありません何にバインドさテキストボックスに無効な入力を挿入するとき、'DefaultModelBinder'はそれはそれもコントローラに達する前'null'する値です設定します!

+0

あなたのコードをもっと投稿できますか?この動作を示すビューとモデル(またはそれらの一部)を見るのが好きです。 – mlibby

1

valueが肯定的で、それはヌルであり、ただstringValueではありませんか?

だから、sayeth MSDNごasオペレータについて:オペレーターが、それは代わりに例外を発生させるの変換失敗時にNULLが生じることを除いて、キャストのようなものであるよう

ザ・。そのページ上の例では

http://msdn.microsoft.com/en-us/library/cscsdfbt%28VS.71%29.aspx

それは数字はあなたが望むように文字列にないasを行うことを示しています。

代わりに.ToString()を試してみるとよいでしょう。

+0

行ごとにデバッグされた簡単なテスト属性が作成されました。文字列を除いて 'value'はnullです。 – BrunoSalvino

+1

decimalやshortやintのような数値的なプロパティとしては非常に不思議ですが、最初はnullにすることはできません。私の推測では、なぜ、nullが渡されているのかを知るために、 'value'がどこから来ているのかを得るために、デバッガのスタックまで歩いていく必要があります。いずれにしても、 intは 'value'として渡され、' as'は失敗し、 'stringValue'はnullになります。 – mlibby

+1

うん、それを得た。より多くのテスト、ここで私は行く...ありがとう! – BrunoSalvino

1

タイプがint、decimalなどのタイプのプロパティにバリデーターを貼り付けようとしている場合は、の値が入ってきます。 int、decimalなどに変換できない場合、これは意図的です。

MVCフレームワークに何をするかを検討してください。このプロパティはint型であるため、MVCフレームワークはint型の値を処理しています。 (技術的には、Nullableのようなものを使用しています<int>)入来値がintに変換できない場合、Nullableで表現する方法はありません< > null任意の文字列を含みます。だから、あなたの検証属性がnullを値にしてしまうのです。

編集:あなたは、このエラーメッセージを制御したい場合は

、最も簡単なオプションは、カスタムバリデータの呼び出しのInt32を持って、その後、文字列にプロパティを変更することです。TryParseまたはユーザーが入力した内容が数値であることを確認するために必要な作業を実行します。次に、基本的にそのプロパティの値の数値形式である個別の読み取り専用プロパティを持つことができます。

もっと複雑ですが、より一般化されている場合、組み込みのDefaultModelBinderを独自の作成物で置き換えることができます。 BindModelメソッドの中から、ModelStateのFormatException型の例外を探して、選択したエラーメッセージに置き換えます。これがどのように行われるかの例については、メソッドDefaultModelBinder.BindPropertyの終わりを参照してください。

+0

これで、DefaultModelBinderがやっていたことを混乱させることが少なくなりました。この動作を完全に修正してください。私はデフォルトの検証メッセージをローカライズするリソースファイルを追加しました。ありがとう! – BrunoSalvino

0

カスタムバリデーターを別のタイプのプライベート変数によってサポートされているプロパティに接続していたとき、同じ問題が発生しました。例:

private DateTime _dt; 

    [LocalizedValidDateAttribute("Resources.DateTimeOffsetModel.App_GlobalResources", "TimePart_Invalid")] 
    public string DateTimeString 
    { 
     get { return _dt.ToString(); } 
     set { DateTime.TryParse(value, out _dt); } 
    }  

DateTimeString = "foobar"を渡すと、次のようになります。 LocalizedValidDateAttribute.IsValid()が発生すると、DateTimeStringの値を取得しようとします。これは、「foobar」が文字列ではないため、nullになります。

うまくいけば、これは私がそれを理解するのにかかった2時間を節約するのに役立つでしょう。

関連する問題