[英]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.