有时候我们的的一些验证需要基于其它的条件。 在 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.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会让代码更易于阅读。