2012-06-23 68 views
0

我已經在模型中的實體實施IValidatableObject,並使用驗證(ValidationContext)執行驗證,往往是複雜的。IValidatableObject驗證()不同場景

我可以使用ValidationContext來區分不同的驗證場景片嗎?

例如舉例來說,一種用戶模型,其中我有3個驗證scenerios:

  • 註冊 - 我要測試的電子郵件是獨一無二的,需要領域的一小部分已經進入
  • 變化的細節 - 不同的電子郵件獨特性檢查,多一點所需的詳細信息註冊成功後,這裏就不再更改密碼,這樣就不需要檢查
  • 更改密碼 - 只有密碼字段來驗證

這是它的一個正確使用,如果是這樣如何是否確保在帖子之後和調用Validate()之前設置了正確的ValidationContext屬性?或者我應該採取完全不同的方法?

+0

我不明白你爲什麼要使用ValidationContext? – VJAI

+0

我真的問是否可以用它。但是,如果這是不好的做法或真的不打算用於確定「驗證組」,那麼請讓我知道。 – mhapps

回答

1

對於我的兩美分價值,我會說你的模型要麼處於有效狀態(應用所有驗證標準),要麼不是。如果在某些情況下,你不想應用驗證,那麼我認爲你應該真的使用一個單獨的模型(實際上是ViewModel)。

在您的示例中,我將創建一個RegisterViewModel用於註冊,另一個用於更改細節EditUserViewModel。其中每個都會有自己的驗證,他們將有一個single responsibility

創建一個在許多不同視圖中重用的胖模型是imho,有點代碼味道。我有很多理由想這個。首先,假設您有一個用於所有與用戶數據交互的模型。它看起來像這樣:

public class UserModel 
{ 
    public int UserId { get; set; } 
    public string Username { get; set; } 
    public string Password { get; set; } 
    public bool IsAdministrator { get; set; } 
} 

後來您決定跟蹤在網站註冊期間使用的瀏覽器。你在哪裏添加?它確實與用戶無關,所以它不應該在UserModel模型上。如果您有單獨的RegisterViewModel,則可以在註冊過程發生變化時根據需要對其進行修改,而不必擔心它會如何影響其使用的其他位置。

例如,如果您在MVC的DefaultModelBinder上使用上述模型,則會出現更嚴重的問題。如here所述,即使您在表單上沒有IsAdministrator字段(通過利用大規模分配漏洞),用戶也可以創建自己的請求並授予自己的管理員權限。同樣,如果使用不帶IsAdministrator屬性的獨立ViewModel,它會減少安全漏洞的表面積。

以上只是一個例子,但我相信你明白了。

+0

我明白你的觀點,但我並不十分熱衷於在不同的驗證場景下複製具有相同或相似屬性的模型,然後將每個模型與單個數據庫對象進行協調。它引入了更多的工作和分散的代碼。 – mhapps

1

IValidatableObject用於對單個模型執行多重驗證。在你的情況下,你有一個User模型,你想要做三個驗證,你可以通過在User模型中實現IValidatableObject來完成。

ValidationContext沒有帶來太多好處(除了提供對上下文的訪問),因爲我們可以直接在Validate方法中訪問所有屬性。

通過IValidatableObject執行與單個模型相關的多個驗證的示例。 (那麼ValidationContext在這裏有什麼用處?)

public class Party : IValidatableObject 
{ 
    [Required(ErrorMessage = "Start date is required")] 
    [FutureDateValidator(ErrorMessage = "Start date should be a future date")] 
    public DateTime StartDate { get; set; } 

    [Required(ErrorMessage = "Duration is required")]  
    public int DurationInHours { get; set; } 

    [Required(ErrorMessage = "No. of joinees is required")] 
    [Range(2, 10, ErrorMessage = "No. of joinees should be minimum 2 and not more than 10")] 
    public int NoOfJoinees { get; set; }  

    public bool Drinks { get; set; } 

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) 
    { 
     if (StartDate.TimeOfDay > new TimeSpan(22 - DurationInHours, 0, 0)) 
     { 
      yield return new ValidationResult("The party should not exceed after 10.00 PM"); 
     } 

     if (NoOfJoinees < 5 && Drinks) 
     { 
      yield return new ValidationResult("Drinks are only allowed if no. of joinees is 5 or more."); 
     } 
    } 
} 
+0

好吧,我可能會嘗試使用ValidationContext來設計它不做的事情,但是如何處理Validate()中的3個場景?你會添加一個屬性/隱藏字段來維護當前的「動作」(註冊,編輯,ChangePass),可以在Validate()中引用,或者之後在頁面控制器中執行它?我想在Validate()中執行所有的驗證。 – mhapps