Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Skip Executing other Validation Rules in the Fluent validation Ruleset, if one of them fails

Is there any way to skips executing the validation rules in the Ruleset if one of them fails.

I have this following rules for my API endpoint

param1, param2, param3

RuleSet  => 
     RuleFor(req => req.param1).NotEmpty().WithMessage("param1 is missing.");
     RuleFor(req => req.param2).NotEmpty().WithMessage("param2 is missing.");
     RuleFor(req => req.param3).NotEmpty().WithMessage("param3 is missing.");
     RuleFor(req => req.param1).Must((req, param1) => IsValidRequest(req)).WithMessage("Invalid request.");

In my IsValidRequest(req) I again have to verify for param1, param2, param3 exist before doing my custom validation as even if the above rules fails all other validations will still continue to try.

like image 522
anveshtummala Avatar asked Apr 26 '17 21:04

anveshtummala


1 Answers

By default, FluentValidation uses Continue cascade mode for invoking validators in rule definition (i.e. it invokes all validators). You should use StopOnFirstFailure mode to stop execution after first validator fails:

ValidatorOptions.CascadeMode = CascadeMode.StopOnFirstFailure;

Note that this will set StopOnFirstFailure mode globally. If you want to specify this mode for particular validators, you can use property of validator class:

public class RequestValidator : AbstractValidator<Request>
{
   public RequestValidator()
   {
       CascadeMode = CascadeMode.StopOnFirstFailure;

       RuleFor(req => req.param1)
          .NotEmpty().WithMessage("param1 is missing.")
          .Must((req, param1) => IsValidRequest(req)).WithMessage("Invalid request.");
       RuleFor(req => req.param2).NotEmpty().WithMessage("param2 is missing.");
       RuleFor(req => req.param3).NotEmpty().WithMessage("param3 is missing.");
   }
}

In the example above Must validator will not be executed if NotEmpty validator fails.


If you want to execute Must validator only when all three parameters are not empty, then When is the best option:

When(req => !String.IsNullOrEmpty(req.param1) 
         && !String.IsNullOrEmpty(req.param2)
         && !String.IsNullOrEmpty(req.param3), () => {
     RuleFor(req => req.param1)
        .Must((req, param1) => IsValidRequest(req)).WithMessage("Invalid request.");
});

You can move precondition check to separate method:

 private bool AllParametersSpecified(Request req)
 {
     return !String.IsNullOrEmpty(req.param1) 
         && !String.IsNullOrEmpty(req.param2)
         && !String.IsNullOrEmpty(req.param3);
 }

And condition will be much more readable:

When(AllParametersSpecified, () => {
     RuleFor(req => req.param1)
        .Must((req, param1) => IsValidRequest(req)).WithMessage("Invalid request.");
});
like image 160
Sergey Berezovskiy Avatar answered Oct 07 '22 15:10

Sergey Berezovskiy