[英]Validating lists in C#
我們正在使用DataAnnotations
來驗證我們的模型。
我們模型的一個非常簡化的版本是:
public class Model
{
public List<Thing> Things;
}
public class Thing
{
[Required]
public string Name {get;set;}
}
現在,有趣的是,如果我創建一個沒有名稱的Thing
並將其添加到模型中,我希望驗證會失敗,但是驗證會通過(震驚!)。
var model = new Model ();
var invalidThing = new Thing (); // No name would fail validation
model.Things.Add(invalidThing );
var validationContext = new ValidationContext(model);
var validationResults = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(model, validationContext, validationResults, true);
Assert.False (isValid); // This fails!
我認為這樣做的原因是,當您驗證模型時,它會驗證每個屬性,但會驗證屬性中的項目(如果是集合)。 Things
是沒有驗證的屬性,因此它可以通過(盡管它包含無效項)。
我們如何確保驗證也可以驗證集合屬性中的項目? 我可以使用一些現成的驗證器嗎?
我已經通過為集合創建一個自定義驗證器來解決此問題,該集合用於檢查每個項目的驗證。 簡化的代碼如下所示:
public class ValidateEachItemAttribute : ValidationAttribute
{
protected readonly List<ValidationResult> validationResults = new List<ValidationResult>();
public override bool IsValid(object value)
{
var list = value as IEnumerable;
if (list == null) return true;
var isValid = true;
foreach (var item in list)
{
var validationContext = new ValidationContext(item);
var isItemValid = Validator.TryValidateObject(item, validationContext, validationResults, true);
isValid &= isItemValid;
}
return isValid;
}
// I have ommitted error message formatting
}
現在以這種方式裝飾模型將按預期工作:
public class Model
{
[ValidateEachItem]
public List<Thing> Things;
}
如果這是ASP.NET MVC
,則另一種選擇是在模型中實現IValidatableObject
。 喜歡:
public class Model: IValidatableObject
{
public List<Thing> Things;
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//your validation logic here
}
}
然后, controller
中ModelState.IsValid
的結果將取決於Validate
方法的實現。 當模型的多個屬性相互依賴時,這很有用。
您問題中的默認行為不足為奇,下面將對其進行描述。 假設您有一個Dictionary<string, Thing>
類型的屬性或Something<Thing>
類型的屬性或Model
包含Thing
對象的無類型集合,那么我們如何期望Validator
對存儲的Thing
對象執行驗證在那些屬性?
我們不能期望Validator
對存儲在這些屬性中的Thing
對象執行驗證,因為它沒有有關如何驗證那些屬性的任何信息。 為了驗證屬性, Validator
為該屬性尋找ValidationAttribute
,並且由於找不到任何驗證屬性,因此不會驗證該屬性。
結果,您需要創建一些ValidationAttribute
來為您執行此操作,並用驗證屬性裝飾屬性。 您可以實現與答案中類似的內容。
注意:在ASP.NET MVC的上下文中,您不必擔心它。 當模型綁定時,即使模型綁定到列表,默認模型綁定器也會照顧所有驗證屬性。
這是默認模型聯編程序的工作。 在創建每個元素時,在為屬性分配值時,它會驗證屬性並將驗證錯誤添加到模型狀態。 最后,所有屬性和對象都經過驗證,並且模型狀態包含所有驗證錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.