未验证FluentValidation集合属性

时间:2015-03-31 21:54:21

标签: asp.net-mvc fluentvalidation

这是我第一次尝试实现FluentValidation,因为我需要涵盖复杂的验证方案。

我正在尝试验证的类具有大量属性,复杂对象和多个集合。

我没有麻烦来验证主类的属性,甚至检查集合是否为空,但在验证每个集合中的对象属性时确实存在问题。

为了实现这一点,我按照此处记录的示例(在“重新使用集合的验证器”下查看): http://fluentvalidation.codeplex.com/wikipage?title=creatingavalidator

这些是我的模型类(减少以提高可读性)

public class Caso
{
public int Id { get; set; } 
public string Descripcion { get; set; }
public List<Medicamento> Medicamentos { get; set; }
}

public class Medicamento
{
public int Id { get; set; }
public string Nombre { get; set; }
}

这些是验证器类:

public class CasoValidator : AbstractValidator<CasoAdverso>
{
    public CasoValidator()
    {
        RuleSet("Iniciar", () =>
        {
            // Validated OK
            RuleFor(x => x.Descripcion).NotEmpty();
            // Validated OK
            RuleFor(x => x.Medicamentos).Must(x => x != null && x.Count > 0).WithMessage("No puede iniciar un caso sin medicamentos cargados");
            RuleFor(x => x.Medicamentos).SetCollectionValidator(new MedicamentoValidator());
        });
    }
}

public class MedicamentoValidator : AbstractValidator<Medicamento>
{
    public MedicamentoValidator()
    {
        // NOT Validated. Even if the object property is empty the error message doesn't appear. I also checked using "NotNull" and "NotEmpty" clauses
        RuleFor(x => x.Nombre).NotNull().WithMessage("Debe especificar un nombre"); 
    }
}

(注意:由于不同的验证模式,我使用的是RuleSet,这取决于工作流中的文档状态)

我正在从控制器手动执行验证(没有MVC集成)

[HttpPost]
public ActionResult Iniciar(Caso c)
{
    CasoValidator validator = new CasoValidator();
    FluentValidation.Results.ValidationResult validate = validator.Validate(c, ruleSet: "Iniciar"); 


    // ...
}

通过此实现,主类的属性已经过验证,但我还需要验证集合中“Medicamento”类的每个属性。

我可以在这里遗漏一些东西吗?是否应使用可用的RuleForEach子句验证?

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

似乎RuleSet设置正在应用于子验证器以及主验证器。

我在xUnit.net测试中测试了你的代码,并确认了它。

如果您更改规则集以执行,您应该会发现它按预期工作:

CasoValidator validator = new CasoValidator();
FluentValidation.Results.ValidationResult validate = validator.Validate(c, ruleSet: "default,Iniciar");

&#39;默认&#39;规则集将适用于MedicamentoValidator规则。

我没有在文档中找到这个,只能通过测试。

这是样本单元测试:

[Fact]
public void Test1()
{

    Caso c = new Caso()
    {
        Id = 1,
        Descripcion = "none",
        Medicamentos = new List<Medicamento>()
    };

    c.Medicamentos.Add(new Medicamento()
    {
        Id = 0,
        Nombre= null
    });

    CasoValidator validator = new CasoValidator();
    FluentValidation.Results.ValidationResult validate = validator.Validate(c, ruleSet: "default,Iniciar");

    Assert.NotEmpty(validate.Errors);
}

更新:我发现Jeremy Skinner对此行为的引用: http://fluentvalidation.codeplex.com/discussions/266920

  

规则集级联到任何子验证器,因此无论哪个规则集都是   选择供顶级验证器使用的也将被使用   儿童验证员。        所以,如果你运行&#34; Minimal&#34; CreateProfileModelValidator上的规则集,然后只有&#34; Minimal&#34;中的规则。规则集   将在上运行 CreateProfileModelValidator和   ProfileValidator。

答案 1 :(得分:0)

作为补充: 名为GroupMemberIds的集合应具有AdminMemebrId:

RuleFor(r => new { r.GroupMemberIds, r.AdminMemberId }).Must(a => a.GroupMemberIds.Contains(a.AdminMemberId));