2010-12-16 39 views
3

如何獲取模型驗證以驗證通用列表屬性中的子對象。ASP.Net MVC 2控制器的TryValidate不驗證模型中的List <>項目

我有一個模型,我試圖驗證,這不是什麼被髮布到服務器,而是一些信息的張貼,並已在服務器上的信息...例如。

... 
public class A { 
    [Required] 
    public string Property1 { get; set; } 
} 
... 
public class B { 
    public List<A> Values { get; set; } 
} 
... 
    if (!TryValidateModel(instanceofB)) 
    { 
     //this should fire, as one of A inside B isn't valid. 
     return View(instanceofB); 
    } 

當我嘗試驗證B的模型實例時,它不會驗證Values集合的驗證屬性。

回答

5

TryValidateModel方法只下降一個級別,因此它僅在B類型的對象上檢查Validation屬性,而不在其嵌套對象上。克服這個的一種方法是定義自己的實施ValidationAttribute的:

public class ListValidationAttribute : ValidationAttribute 
{ 
    public override bool IsValid(object value) 
    { 
     IEnumerable enumerable = value as IEnumerable; 
     // If the input object is not enumerable it's considered valid. 
     if (enumerable == null) 
     { 
      return true; 
     } 
     foreach (object item in enumerable) 
     { 
      // Get all properties on the current item with at least one 
      // ValidationAttribute defined. 
      IEnumerable<PropertyInfo> properties = item.GetType(). 
       GetProperties().Where(p => p.GetCustomAttributes(
       typeof(ValidationAttribute), true).Count() > 0); 
      foreach (PropertyInfo property in properties) 
      { 
       // Validate each property. 
       IEnumerable<ValidationAttribute> validationAttributes = 
        property.GetCustomAttributes(typeof(ValidationAttribute), 
        true).Cast<ValidationAttribute>(); 
       foreach (ValidationAttribute validationAttribute in 
        validationAttributes) 
       { 
        object propertyValue = property.GetValue(item, null); 
        if (!validationAttribute.IsValid(propertyValue)) 
        { 
         // Return false if one value is found to be invalid. 
         return false; 
        } 
       } 
      } 
     } 
     // If everything is valid, return true. 
     return true; 
    } 
} 

現在List<A>可以使用屬性進行驗證:

public class B 
{ 
    [ListValidation] 
    public List<A> Values { get; set; } 
} 

我沒有爲上述方法測試表現得淋漓盡致,但如果在你的情況下,這是一個問題,另一種方法是使用助手功能:

if (!ValidateB(instanceofB)) 
    { 
     //this should fire, as one of A inside B isn't valid. 
     return View(instanceofB); 
    } 

... 

public bool ValidateB(B b) 
{ 
    foreach (A item in b.Values) 
    { 
     if (!TryValidateModel(item)) 
     { 
      return false; 
     } 
    } 
    return true; 
} 
+0

將此標記爲現在的正確答案...理想情況下,希望讓孩子標記適當的模型狀態錯誤,但現在用手執行孩子錯誤... – Tracker1 2011-02-13 15:36:40

+0

@Jeroen:你能告訴我你是如何學習TryValidateModel只能在一個層次而不是在子項目上工作的事實? – DavidS 2011-11-16 16:39:54

+0

@DavidS:使用類瀏覽器(Reflector,IL Spy)進行檢查。 – Jeroen 2011-11-16 17:17:19

1

我有一個類似的問題th在我通過避免完全調用TryValidate來修復。我調用TryValidate的原因是因爲我需要對模型進行一些更改,然後進行驗證。我最終爲模型創建了一個接口,並將默認的模型綁定器替換爲識別接口並調用我的方法的接口。這一切都發生在框架調用第一次驗證之前(這是遞歸的)。