2010-11-30 66 views
1

這裏有一個簡單的驗證屬性我寫了強制執行數隻字符串(我用它來驗證電話號碼,郵政編碼和一樣):ValidationAttribute的值總是空

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; 
    } 

} 

的問題是,使用時驗證不是字符串,比方說,一個小數,短,int或別的什麼,object value總是null。爲什麼要驗證僅限數字的小數?因爲如果我不這樣做,我得到默認的驗證消息「值‘X’無效‘propertyName的’。我意識到默認驗證消息的特定問題的解決方案。

我只是想知道爲什麼它總是空...

順便說一句,我使用VS2008,ASP.NET MVC 2(最終),.NET 3.5 SP1。

回答

1

好,感謝@mcl的提示調試一路下跌(查看>控制器>模型)來驗證屬性!

這裏發生了什麼:在綁定到任何一個文本框,這不是模型中的一個串中插入無效的輸入時,'DefaultModelBinder'將它的值'null'達到甚至控制器之前! (任何人有更多的信息?我會很高興!)

1

你肯定是value是零,而不僅僅是stringValue

所以sayeth的MSDN你as運營商:

as運算符相似,但它產生在轉換失敗而不是引發異常空鑄造。

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

在該網頁上的例子就說明NUMERICS不as爲字符串你想要的方式。

你可以嘗試.ToString()代替。

+0

創建一個簡單的測試屬性,逐行掃描:`value`爲空,除了字符串。 – BrunoSalvino 2010-12-01 00:55:40

+1

非常神祕,因爲像decimal或short或int這樣的數字屬性首先不能爲null。我的猜測是,你需要在調試器中返回堆棧以查看「value」來自哪裏,以瞭解爲什麼傳入null。無論如何,如果確實得到小數或小數或一個int作爲`value`傳入,`as`將失敗,`stringValue`將爲空。 – mlibby 2010-12-01 01:03:06

+1

是的,明白了。更多的測試,在這裏我去...謝謝! – BrunoSalvino 2010-12-01 01:04:07

1

如果你的方案是你試圖將你的驗證器粘在int,decimal等的屬性上,值進來不能轉換爲int,decimal等,那麼這是有意的。

考慮你要求MVC框架做什麼。該物業是int類型,所以MVC框架正在與int類型的值。 (從技術上講,它的工作方式與Nullable <int>類似。)如果傳入值不能轉換爲int,則無法將其表示爲可空的<int>而不是null,因爲該類型不能包含任意字符串。所以這就是爲什麼您的驗證屬性最終會以null作爲值。

編輯:

如果你想控制這個錯誤信息,最簡單的方法是將屬性更改爲一個字符串,然後讓你自定義的驗證電話的Int32。TryParse或任何你需要它來做的事情,以驗證用戶輸入的內容是數字。然後,您可以擁有一個單獨的只讀屬性,該屬性基本上是該屬性值的數字形式。

更復雜但更普遍的是,您可以用您自己創建的內置DefaultModelBinder替換。從BindModel方法中,在ModelState中查找FormatException類型的異常,然後用您選擇的錯誤消息替換它們。查看方法DefaultModelBinder.BindProperty的結尾,以獲得如何完成的示例。

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」不是字符串。

希望這會幫助其他人在那裏保存2小時,我花了我的時間。