Остановить проверку флажка при первом отказе

Я определяю проверку для объектов Request. Я бы хотел, чтобы валидатор остановился на самом первом провале, а не только на той же цепочке. В приведенном ниже примере, если мой объект TechnicalHeader имеет значение null, я получаю исключение NullReference, когда проверка достигает правила для TechnicalHeader.MCUserid.

В плохих словах я хотел бы выполнить условную проверку по последним трем правилам в приведенном ниже коде, в соответствии с результатом первого правила

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");
                }
            );
        }
    }
}

Ответ 1

Просто запустите null перед запуском правил, которые зависят от них, используя условие When.

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");
});

Ответ 2

Просто добавьте SetValidator перед запуском правил, которые зависят от них, используя Custom условие:

//if InpatOrderImportValidatorBllNode fail ,the custom method cannot be executed
RuleFor(x => x).Cascade(CascadeMode.StopOnFirstFailure)
               .SetValidator(new InpatOrderImportValidatorBllNode())
               .Custom((input, context) => {          
                  context.AddFailure(new ValidationFailure("DrugTypeName", "fail"));
               });

Ответ 3

Вы можете использовать DependentRules.

RuleFor(object => object.String)
    .NotNull()
    .DependentRules(() =>
    {
        RuleFor(object => object.String)
            .NotEmpty()
            .Matches("^[A-Z]{3}$");
    });

Тогда вы не дублируете проверочный код.

Вы даже можете добавить метод расширения, чтобы не дублировать RuleFor.

    public static IRuleBuilderOptions<T, TProperty> DependentRules<T, TProperty>(
        this IRuleBuilderOptions<T, TProperty> currentRule, 
        Action<IRuleBuilderOptions<T, TProperty>> action)
    {
        return currentRule.DependentRules(() => action(currentRule));
    }

Итак, определенный код:

RuleFor(object => object.String)
    .NotNull()
    .DependentRules(currentRule =>
    {
        currentRule
            .NotEmpty()
            .Matches("^[A-Z]{3}$");
    });