0

I have this case when I need to validate a model with two validators:

1) a BaseValidator that has some common rules.

2) [Variable]CustomValidator which is determined based on one of the Model's properties.

Code that will show you what I approximately intend to do (of course it does not work since there is not such method as AlsoValidateWith()) is below:

[Validator(typeof(AnimalValidator))]
public class AnimalModel
{
    public string Type { get; set }
    public int NumberOfLegs { get; set; }
    public string Color { get; set; }
    public int NumberOfEyes { get; set; }
    public bool HasWings { get; set; }
}

public class AnimalValidator: AbstractValidator<AnimalModel>
{
    public AnimalValidator()
    {
        RuleFor(x => x.NumberOfEyes).Equal(2);
        RuleFor(x => x).AlsoValidateWith(new DogValidator()).When(x => x.Type == "Dog");
        RuleFor(x => x).AlsoValidateWith(new CatValidator()).When(x => x.Type == "Cat");
    }
}

public class DogValidator: AbstractValidator<AnimalModel>
{
    public DogValidator()
    {
        RuleFor(x => x.Color).Equal("Black");
        RuleFor(x => x.NumberOfLegs).Equal(2);
        RuleFor(x => x.HasWings).Equal(false);
    }
}

Any help is appreciated!

Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79

1 Answers1

1

I don't think this is possible using the When method unless you're validating a "child" model.

However, the calling code (e.g. your controller) could instead invoke the appropriate validator. Here's a simplified example:

public ActionResult SomeAction(AnimalModel model)
{    
    ModelState.Clear();

    if (model.Type == "Dog")
        model.ValidateModel(new DogFullValidator(), ModelState);
    else if (model.Type == "Cat")
        model.ValidateModel(new CatFullValidator(), ModelState);

    // etc.
}

The above example uses a simple extension method to call the fluent validation:

public static class ValidationExtensions
{
    public static ModelStateDictionary ValidateModel<TModel, TValidator>(this TModel model, TValidator validator, ModelStateDictionary modelState)
        where TModel : class
        where TValidator : AbstractValidator<TModel>
    {
        var result = validator.Validate(model);

        result.AddToModelState(modelState, string.Empty);

        return modelState;
    }
}
MarkG
  • 1,859
  • 1
  • 19
  • 21
  • that looks great, but `result` does not have method `AddToModelState`. Is that another extension that you wrote? May I see the code for it, if this is the case? – Dmitry Efimenko Dec 20 '12 at 18:17
  • it's defined in `FluentValidation.Mvc` so you'll need a using statement for it – MarkG Dec 21 '12 at 12:03