9

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);
6
  • 1
    Hi, what's SimpleListValidator? Something is missing in the question? Commented Aug 27, 2015 at 11:37
  • 1
    I think it doesn't matter. It's some kind of validator which I want to apply on my list, but this "SimpleListValidator" takes one param in constructor and this is the case. Now I'm not able to pass lambda expression "x => x.Type" and I don't know how to build proper extension method like SetCollectionValidator. Commented Aug 27, 2015 at 12:12
  • 1
    If I understand right, SimpleListValidator CTOR gets 1 arg: Type, if so: Consider using typeof(X): new SimpleListValidator(typeof(x)). Will it work? Commented Aug 27, 2015 at 12:17
  • 1
    But x.Type it's not type of object, this is a field (enum) in class, it can be any other field etc. x.Name, x.Age.. Commented Aug 27, 2015 at 12:23
  • 1
    Can you paste SimpleListValidator CTOR.. Commented Aug 27, 2015 at 13:13

2 Answers 2

11

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.

Sign up to request clarification or add additional context in comments.

Comments

6

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().

1 Comment

Great, it's what I was looking for :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.