Adrian Bystrek
Adrian Bystrek

Reputation: 608

Fluent Validation - pass parameter to collection validator

I'm using fluent validation i ASP.NET MVC application and I've had a problem. This is my rule:

RuleFor(x => x.SimpleList)
       .SetCollectionValidator(new SimpleListValidator())
       .When(x => x.Type == SimpleEnum.SpecificType);

I want to pass x.Type param to SimpleListValidator, how can I do this? Some kind of extension method? It should looks like:

    RuleFor(x => x.SimpleList)
       .SetCollectionValidator(new SimpleListValidator(x => x.Type))
       .When(x => x.Type == SimpleEnum.SpecificType);

Upvotes: 9

Views: 16896

Answers (2)

Jan W
Jan W

Reputation: 474

It is possible and you can do it like this:

RuleFor(x => x.SimpleList)
   .SetCollectionValidator(model => new SimpleListValidator(model))
   .When(x => x.Type == SimpleEnum.SpecificType);

In your SetCollectionValidator class you have to create a constructor accepting your model as a parameter (or anything else you'd like to pass to the validator). Remember though that you should leave a parameter-less constructor in the SimpleListValidator class.

Upvotes: 11

Electrionics
Electrionics

Reputation: 6772

After you set collection validator for property - you can forget about fact, that main model and (n - 1) submodels exists except submodel being currently validated. And there is no way to pass main model as a parameter in SetCollectionValidator.

So you have to use RuleForEach method instead of setting collection validator:

RuleForEach(x => x.SubEntities)
    .Must((model, submodel) => IsValidFirst(submodel, model)) // your rules should go here to be applicable to each collection item
        .WithMessage("The item with values {0}, {1} has duplicates in collection of {2} items",
            (model, submodel) => submodel.Field1,
            (model, submodel) => submodel.Field2,
            (model, submodel) => model.SubEntities.Count); // for error message building you can access both model and submodel being validated
    .Must((model, submodel) => IsValidSecond(submodel, model)) // yet another rule
        .WithMessage("...")
    .When(model => 
        model.Type == SimpleEnum.SpecificType) // can access to main model only, but it is enough for your purposes

I guess that possibility to tell child validator about fact, that parent model could exists, should be implemented in future, but right now there is the only working approach, mentioned above.

UPDATE

You can create custom ModelBinder, that would set Parent property of each subentity to main entity value, and continue using SetCollectionValidator().

Upvotes: 6

Related Questions