Fluent Validation 9.3.0中ChildRules下CascadeMode.Stop不生效的问题
解决FluentValidation 9.3.0中仅返回第一个验证失败消息的问题
你当前的代码无法实现“仅返回第一个失败消息”的原因是:在RuleFor(f => f)上设置的CascadeMode.Stop(9.3.0中应为CascadeMode.StopOnFirstFailure)仅作用于根对象本身的验证规则,不会传递到ChildRules内部的子属性规则中。ChildRules会创建独立的规则集,不受上层级联模式的影响。
要在不修改全局CascadeMode.Continue的前提下,让这段代码仅返回第一个失败消息,有两种可行方案:
方案一:使用自定义子Validator(推荐)
创建一个针对DefaultName类型的独立Validator,在其中设置CascadeMode.StopOnFirstFailure,这样该Validator内的所有规则会在第一个失败时停止验证:
// 自定义DefaultName的验证器 public class DefaultNameValidator : AbstractValidator<DefaultName> { public DefaultNameValidator() { // 设置当前验证器内的级联模式为第一个失败即停止 CascadeMode = CascadeMode.StopOnFirstFailure; RuleFor(f => f.Primary) .Must(f => !char.IsDigit(f.First())) .WithMessage("IsDigit1"); RuleFor(f => f.Secondary) .Must(f => !char.IsDigit(f.First())) .WithMessage("IsDigit2"); RuleFor(f => f.Primary) .MinimumLength(10) .WithMessage("MinimumLength1"); RuleFor(f => f.Secondary) .MinimumLength(10) .WithMessage("MinimumLength2"); } } // 在主验证器中引用该子验证器 RuleFor(f => f.DefaultName) .SetValidator(new DefaultNameValidator());
方案二:直接在子属性规则上设置级联模式
如果不想创建单独的Validator,可以将CascadeMode.StopOnFirstFailure直接应用到DefaultName的规则上,再通过ChildRules定义子属性规则:
RuleFor(f => f.DefaultName) .Cascade(CascadeMode.StopOnFirstFailure) .ChildRules(f => { RuleFor(f => f.Primary) .Must(f => !char.IsDigit(f.First())) .WithMessage("IsDigit1"); RuleFor(f => f.Secondary) .Must(f => !char.IsDigit(f.First())) .WithMessage("IsDigit2"); RuleFor(f => f.Primary) .MinimumLength(10) .WithMessage("MinimumLength1"); RuleFor(f => f.Secondary) .MinimumLength(10) .WithMessage("MinimumLength2"); });
注意:FluentValidation 9.x版本中,CascadeMode枚举的成员为Continue和StopOnFirstFailure,原CascadeMode.Stop已重命名为StopOnFirstFailure,请确保使用正确的枚举值。
内容的提问来源于stack exchange,提问作者Unknown Artist
相关产品推荐
相关产品推荐

