FluentValidation条件验证子属性:仅HasDetails为true时验证子模型?
问题描述
我希望仅当父对象PersonDetailsViewModel的HasDetails属性为true时,才对复杂子属性BasicDetails进行验证。
我的视图模型定义如下:
public class PersonDetailsViewModel { public bool? HasDetails { get; set; } public BasicDetailsViewModel? BasicDetails { get; set; } }
BasicDetailsViewModel的定义:
public class BasicDetailsViewModel { public string? FirstName { get; set; } public string? Country { get; set; } }
我为PersonDetailsViewModel编写的验证器PersonDetailsViewModelValidator代码如下:
public class PersonDetailsViewModelValidator : AbstractValidator<PersonDetailsViewModel> { public PersonDetailsViewModelValidator() { RuleFor(model => model.BasicDetails) .SetValidator(new BasicDetailsViewModelValidator()) .When(model => model.HasDetails == true); } }
BasicDetailsViewModelValidator的代码:
public class BasicDetailsViewModelValidator : AbstractValidator<BasicDetailsViewModel?> { public BasicDetailsViewModelValidator() { RuleFor(model => model.FirstName) .NotEmpty().WithMessage(ValidationMessages.Required); RuleFor(model => model.Country) .NotEmpty().WithMessage(ValidationMessages.Required); } }
我在BasicDetailsViewModelValidator的构造函数中设置了断点,但无论HasDetails的值是什么,只要PersonDetailsViewModelValidator被调用,断点就会触发。我原本预期只有当HasDetails为true时才会触发该断点。请问我是否操作有误,还是这是预期行为?
解答
这是预期行为,你混淆了「验证器实例化」和「验证规则执行」的时机:
- 当
PersonDetailsViewModelValidator的构造函数执行时,你直接new BasicDetailsViewModelValidator()创建了子验证器实例,此时子验证器的构造函数会立即执行——这是验证器的规则初始化阶段,和When条件无关。 When(model => model.HasDetails == true)控制的是子验证器的规则是否会被应用到目标对象上,而非子验证器是否被实例化。也就是说,只有当HasDetails为true时,BasicDetails的FirstName和Country非空规则才会实际执行验证;但子验证器的构造函数在父验证器初始化时就已经运行完成了。
如果要验证逻辑是否符合预期,建议在BasicDetailsViewModelValidator的规则逻辑(比如NotEmpty()的执行环节)添加断点,而非构造函数中。此时你会发现:当HasDetails为false时,这些规则断点不会触发;只有HasDetails为true时,才会进入子验证器的规则执行流程。
内容的提问来源于stack exchange,提问作者KTOV
相关产品推荐
相关产品推荐

