FluentValidation中属性为Null时SetValidator未触发的问题咨询
这确实是FluentValidation的设计预期
FluentValidation默认会跳过对null属性的子验证器调用,核心原因有两点:
- 避免潜在的空引用异常,毕竟很多验证逻辑依赖属性的非空状态
- 遵循"显式声明必填性"的设计原则:框架认为属性是否为必填是父验证器的职责,子验证器只负责验证非空状态下的属性规则
如果你想让自定义验证器自己处理null场景,有两种可行方案:
方案1:重写自定义验证器的PreValidate方法
默认的PreValidate会在属性值为null时返回false,直接跳过后续验证逻辑。重写这个方法让它始终返回true,就能强制执行自定义验证器里的所有规则,包括空值校验:
public class BankRoutingNumberValidator : AbstractValidator<string?> { public BankRoutingNumberValidator() { // 包含null和空字符串的校验 RuleFor(x => x).NotNull().WithMessage("路由编号不能为null"); RuleFor(x => x).NotEmpty().WithMessage("路由编号不能为空字符串"); RuleFor(x => x).Length(9).WithMessage("路由编号必须为9位"); // 格式、校验和等其他规则... } protected override bool PreValidate(ValidationContext<string?> context, ValidationResult result) { // 强制执行所有验证规则,无论值是否为null return true; } }
方案2:在父验证器中使用CascadeMode调整验证行为
如果不想修改自定义验证器,可以在父验证器的规则链中设置CascadeMode.Continue,结合NotNull()和子验证器,不过这种方式还是需要在父验证器声明必填性,只是能确保后续验证执行:
RuleFor(payment => payment.RoutingNumber) .Cascade(CascadeMode.Continue) .NotNull() .SetValidator(new BankRoutingNumberValidator());
但显然方案1更符合你的需求——让自定义验证器完全接管包括空值在内的所有校验逻辑。
内容的提问来源于stack exchange,提问作者BJ Safdie
相关产品推荐
相关产品推荐

