Search code examples
validationservicestackfluentvalidation

Stop Fluent Validation on first failure


i'm defining a validation for my Request objects. I would like the validator to stop on the very first failure, not only the one on the same chain. In the example below, if my TechnicalHeader object is null, i get a NullReference exception when the validation reaches the rule for TechnicalHeader.MCUserid.

In poor words, i would like to do a conditional validation over the last three rules in the code below, according to the result of the first rule

using System;
using ServiceStack.FluentValidation;
using MyProj.Services.Models;

namespace MyProj.Services.BaseService.Validators
{
    public class BaseValidator<T> : AbstractValidator<T>
        where T : RequestBase
    {
        public BaseValidator()
        {
            RuleSet(ServiceStack.ApplyTo.Put | ServiceStack.ApplyTo.Post, 
                () =>
                {
                    this.CascadeMode = CascadeMode.StopOnFirstFailure;
                    RuleFor(x => x.TechnicalHeader).Cascade(CascadeMode.StopOnFirstFailure).NotNull().WithMessage("Header cannot be null");
                    RuleFor(x => x.TechnicalHeader).NotEmpty().WithMessage("Header cannot be null");
                    RuleFor(x => x.TechnicalHeader.Userid).NotEmpty().WithMessage("Userid cannot be null or an empty string");
                    RuleFor(x => x.TechnicalHeader.CabCode).GreaterThan(0).WithMessage("CabCode cannot be or less than 0");
                    RuleFor(x => x.TechnicalHeader.Ndg).NotEmpty().WithMessage("Ndg cannot be null or an empty string");
                }
            );
        }
    }
}

Solution

  • Just check for null before running the rules that depend on them, using a When condition.

    this.CascadeMode = CascadeMode.StopOnFirstFailure;
    RuleFor(x => x.TechnicalHeader).NotNull().WithMessage("Header cannot be null");
    
    // Ensure TechnicalHeader is provided
    When(x => x.TechnicalHeader != null, () => {
        RuleFor(x => x.TechnicalHeader.Userid).NotEmpty().WithMessage("Userid cannot be null or an empty string");
        RuleFor(x => x.TechnicalHeader.CabCode).GreaterThan(0).WithMessage("CabCode cannot be or less than 0");
        RuleFor(x => x.TechnicalHeader.Ndg).NotEmpty().WithMessage("Ndg cannot be null or an empty string");
    });