Blazor中Fluent Validation复杂子模型条件验证问题求助
在Blazor中实现基于父类属性的Fluent Validation子集合条件验证
你遇到的问题是之前的Custom验证没有正确关联到子项的具体字段,错误提示无法精准定位到对应的输入控件。下面提供两种可行的解决方案:
方案一:使用ChildRules结合父类上下文验证(推荐)
直接在AValidator中通过RuleForEach遍历每个B项,结合ChildRules和When条件验证Bfield2的非空性,同时能访问父类A的Afield2属性:
public class AValidator : AbstractValidator<A> { public AValidator() { RuleFor(s => s.Afield1).NotEmpty().WithMessage("Select The Afield1"); RuleForEach(s => s.Bs).SetValidator(new BValidator()); // 新增针对Bfield2的条件验证 RuleForEach(s => s.Bs) .ChildRules(b => { b.RuleFor(x => x.Bfield2) .NotEmpty().WithMessage("Bfield2 not entered") // When的第一个参数是父类A的实例,第二个是当前遍历的B项 .When((parentA, currentB) => parentA.Afield2 == "KI"); }); } }
这种方式的优势:
- 错误会精准关联到每个
B项的Bfield2字段,Blazor会自动在对应的输入控件旁显示验证提示 - 代码简洁,无需手动处理属性路径或索引
方案二:在子验证器中传入父类上下文
如果希望把B的验证逻辑封装在BValidator中,可以通过构造函数传入获取父类Afield2的委托:
修改BValidator
public class BValidator : AbstractValidator<B> { private readonly Func<string> _getAfield2; // 带参数的构造函数,接收获取父类Afield2的委托 public BValidator(Func<string> getAfield2) { _getAfield2 = getAfield2; RuleFor(s => s.Bfield1).NotEmpty().WithMessage("Select Bfield1"); RuleFor(s => s.Bfield2) .NotEmpty().WithMessage("Bfield2 not entered") .When(() => _getAfield2() == "KI"); } // 无参构造函数,兼容不需要父类上下文的场景 public BValidator() : this(() => null) { } }
在AValidator中使用
public class AValidator : AbstractValidator<A> { public AValidator() { RuleFor(s => s.Afield1).NotEmpty().WithMessage("Select The Afield1"); // 为每个B项传递父类A的Afield2获取委托 RuleForEach(s => s.Bs) .SetValidator(parentA => new BValidator(() => parentA.Afield2)); } }
原Custom验证未生效的原因
你之前的代码是针对整个Bs集合添加错误,没有指定具体的属性路径,导致Blazor无法将错误关联到对应的Bfield2输入控件。如果要修复原代码,可以手动指定属性路径:
RuleFor(s => s.Bs).Custom((bs, context) => { if (context.InstanceToValidate.Afield2 == "KI") { for (int i = 0; i < bs.Count; i++) { if (string.IsNullOrEmpty(bs[i].Bfield2)) { // 指定错误对应的属性路径,格式为集合名[索引].属性名 context.AddFailure($"Bs[{i}].Bfield2", "Bfield2 not entered"); } } } });
但这种方式需要手动处理索引和路径,不如前两种方案简洁可靠。
内容的提问来源于stack exchange,提问作者rakshith
相关产品推荐
相关产品推荐

