Home > Net >  FluentValidation conditional rules
FluentValidation conditional rules

Time:10-28

I want to make a conditional to execute the CPF rule only when dealing with a CPF with length == 11, and execute the CNPJ rule only when dealing with a CNPJ with length > 11.

However, I realized that even with When, both methods are executed (MustBeAValidCPF and MustBeAValidCNPJ).
Is there a way to run it only when the When returns true?

RuleFor(x => x.Code)
    .NotEmpty()
    .WithMessage(m => "Code cannot be empty")
    .MinimumLength(11)
    .WithMessage(m => "Code minimum length is 11")
    .MustBeAValidCPF()
    .When(x => x.Code?.Length == 11)
    .MustBeAValidCNPJ()
    .When(x => x.Code?.Length > 11);

Methods (extensions):

public static IRuleBuilderOptions<T, string> MustBeAValidCPF<T>(this IRuleBuilder<T, string> ruleBuilder)
{
    return ruleBuilder.IsValidCPF().WithMessage("CPF is invalid");
}

public static IRuleBuilderOptions<T, string> MustBeAValidCNPJ<T>(this IRuleBuilder<T, string> ruleBuilder)
{
    return ruleBuilder.IsValidCNPJ().WithMessage("CNPJ is invalid");
}

CodePudding user response:

As described in the documentation, the When method has an optional parameter to modify this behavior.

By default:

If the second parameter is not specified, then it defaults to ApplyConditionTo.AllValidators, meaning that the condition will apply to all preceding validators in the same chain.

To achieve what you want, pass ApplyConditionTo.CurrentValidator as the second parameter of both calls to When:

RuleFor(x => x.Code)
    .NotEmpty()
    .WithMessage(m => "Code cannot be empty")
    .MinimumLength(11)
    .WithMessage(m => "Code minimum length is 11")
    .MustBeAValidCPF()
    .When(x => x.Code?.Length == 11, ApplyConditionTo.CurrentValidator)
    .MustBeAValidCNPJ()
    .When(x => x.Code?.Length > 11, ApplyConditionTo.CurrentValidator);
  • Related