首次失败时停止流利验证

Piz*_*boy 16 validation fluentvalidation servicestack

我正在为我的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");
                }
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*ott 33

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");
});
Run Code Online (Sandbox Code Playgroud)

  • @Pizzaboy`CascadeMode.StopOnFirstFailure`只能应用于**当前规则链**,而不适用于后续规则.当你将规则的主题,即`RuleFor(x = x.TechnicalHeader)`更改为`RuleFor(x = x.TechnicalHeader.UserId)时,你必须开始一个新的链.FluentValidation不能替代检查null,使用`When`子句来覆盖此检查.ServiceAack的FluentValidation中没有使用`OnAnyFailure`,它也是您链接的FluentValidation包的子集. (4认同)

小智 7

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"));
               });
Run Code Online (Sandbox Code Playgroud)


Mic*_*l17 7

您可以使用 DependentRules。

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

然后你不要重复验证代码。

你甚至可以添加一个扩展方法来避免重复 RuleFor。

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

所以确定的代码:

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