NibblyPig
NibblyPig

Reputation: 52952

Can I have validators inside validators with fluent validation

c# Pseudo-code

If I have a class

class Person
{
  string Name
  date DOB
  Address address
}

I can make a PersonValidator to validate Person

but since Address is a complex type, and sometimes I want to validate it separately, I have a PersonValidator and an AddressValidator. Question is, how do I use my AddressValidator inside my PersonValidator?

class PersonValidator : AbstractValidator<Person>
{
   PersonValidator()
   {
       RuleFor(c => c.Name).NotEmpty();

       var addressValidator = new AddressValidator();
       addressValidator.Validate( person.address ) // ???
    }
}

Upvotes: 7

Views: 5344

Answers (2)

dummyDev
dummyDev

Reputation: 461

You can invoke the .SetValidator(IValidator) method.

class PersonValidator : AbstractValidator<Person>
{
   PersonValidator()
   {
       // CascadeMode = CascadeMode.StopOnFirstFailure;

       RuleFor(c => c.Name)
           .NotEmpty().WithErrorCode("name_required");

       // Checks that the IEnumerable<Address> has at least 1 item
       RuleFor(c => c.Address)
           .NotEmpty().WithErrorCode("addresses_required");

       RuleForEach(c => c.Address)
           .SetValidator(new AddressValidator());

    }
}

class AddressValidator : AbstractValidator<Address>
{
   AddressValidator()
   {
       // CascadeMode = CascadeMode.Continue;

       RuleFor(c => c.Postcode)
           .NotEmpty().WithErrorCode("postcode_required");
   }
}

Upvotes: 13

Rafal
Rafal

Reputation: 12639

You can override validate method:

public override ValidationResult Validate(ValidationContext<T> context) {
    var baseResult = base.Validate(context);
    var result = new AddressValidator().Validate(new ValidationContext<Address>(context.InstanceToValidate.Address);
    return new ValidationResult(baseResult.Errors.Concat(result.Errors));
}

Do this for async method variation as well.

Upvotes: 2

Related Questions