Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ) // ???
    }
}
like image 854
NibblyPig Avatar asked Dec 11 '22 04:12

NibblyPig


2 Answers

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");
   }
}
like image 176
dummyDev Avatar answered Dec 25 '22 22:12

dummyDev


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.

like image 28
Rafal Avatar answered Dec 25 '22 22:12

Rafal