FluentValidation 验证条件 condition

有时候我们的的一些验证需要基于其它的条件。 在 fluentValidation中我们可以用 When Unless来设定条件


public class Customer
{
    public decimal CustomerDiscount { get; set; }

    public bool IsPreferredCustomer { get; set; }

    public string CreditCardNumber { get; set; }
}

public class MyValidator : AbstractValidator<Customer>
{
    public MyValidator()
    {
        RuleFor(customer => customer.CustomerDiscount).GreaterThan(0).When(customer => customer.IsPreferredCustomer);
    }
}

static void Main(string[] args)
{
    var validator = new MyValidator();
    var result = validator.Validate(new Customer() { IsPreferredCustomer = true });

    foreach (var item in result.Errors)
    {
        Console.WriteLine(item.ErrorMessage);
        // 输出 'Customer Discount' 必须大于 '0'。
    }

    result = validator.Validate(new Customer() { IsPreferredCustomer = false });
    //没有出错消息
}

如果其它的属性也想用这个条件的话,我们可以把When放在最顶级的地方。

public class MyValidator : AbstractValidator<Customer>
{
    public MyValidator()
    {
        When(customer => customer.IsPreferredCustomer, () => {
            RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
            RuleFor(customer => customer.CreditCardNumber).NotNull();
        });
        
    }
}

我们也可以在When后面直接链上OtherWise 这样IsPrefereredCustomer为false的时候则会验证里面的规则

When(customer => customer.IsPreferredCustomer, () => {
                RuleFor(customer => customer.CustomerDiscount).GreaterThan(0);
                RuleFor(customer => customer.CreditCardNumber).NotNull();
            }).Otherwise(() => {
                RuleFor(customer => customer.CustomerDiscount).Equal(0);
            }); ;

ApplyConditionTo

没有指定的情况这个默认情况是 ApplyConditionTo.AllValidators 就是说When前面的各个验证都处在这个条件的控制下。

RuleFor(customer => customer.CustomerDiscount).Equal(5).GreaterThan(0).When(customer => customer.IsPreferredCustomer);

result = validator.Validate(new Customer() { IsPreferredCustomer = false });
//result没有错误消息

如果 when里面指定了 ApplyConditionTo.CurrentValidator 则这个when只控制了 GreaterThan(0)

RuleFor(customer => customer.CustomerDiscount)
      .Equal(5)
      .GreaterThan(0)
      .When(customer => customer.IsPreferredCustomer, ApplyConditionTo.CurrentValidator);
      
      result = validator.Validate(new Customer() { IsPreferredCustomer = false });
// 会看到一个错误消息 'Customer Discount' 应该和 '5' 相等。

设置级联模式

我们可以设置级联模式,来决定当链中的特定验证器发生故障时,是否要继续执行下一条验证规则

想象一下,我们要定义两个验证规则如下:

RuleFor(x => x.Surname).NotNull().NotEqual("foo");

当验证器工作的时候会先检查Surname是不是null然后再检查Surname是不是等于foo 当第一个检查没有通过的时候,fluentValidation还是会继续检查第二个是不是等于 foo 有时候第一个检查没有通过,我们不想再验证第二个了。这个时候可以设置 CascadeMode.Stop

RuleFor(x => x.Surname).Cascade(CascadeMode.Stop).NotNull().NotEqual("foo");

我们也可以在全局设置

ValidatorOptions.Global.CascadeMode = CascadeMode.Stop;

也可以在每个验证器开始的时候设置

public class PersonValidator : AbstractValidator<Person> 
{
  public PersonValidator() 
  {
    // First set the cascade mode
    CascadeMode = CascadeMode.Stop;

    RuleFor(x => x.Surname).NotNull().NotEqual("foo");
    RuleFor(x => x.Forename).NotNull().NotEqual("foo");
  }
}

规则依赖

默认情况下, FluentValidation下的所有的规则都是独立的不会互相影响。为了异步验证FluentValidation特意这样做的。如果我们希望某些规则是在其它的规则验证成功后执行。就可以用DependentRules

RuleFor(x => x.Surname).NotNull().DependentRules(() => {
  RuleFor(x => x.Forename).NotNull();
});

在Surname不为空的的时候 forename这个规则才会被执行。 通常来说使用 when会让代码更易于阅读。

最近更新的
...