繁体   English   中英

验证C#中的列表

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

然后, controllerModelState.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM