使用FluentValidation验证IEnumerable模型时出现索引器应用错误
解决FluentValidation验证IEnumerable时的"Could not apply an Indexer"错误
问题根源
直接用AbstractValidator<IEnumerable<Item>>作为根验证器时,FluentValidation没法为集合元素生成有效的属性链索引——因为IEnumerable<T>本身没有索引器,而RuleForEach需要追踪元素位置来生成错误信息,这就触发了这个异常。
推荐解决方案
不要直接验证IEnumerable<Item>,而是给集合套一个包装类,针对包装类写验证器,这是符合FluentValidation设计逻辑的标准做法。
修改后的完整代码
首先定义包装集合的模型类:
public class ItemListModel { public IEnumerable<Item> Items { get; set; } }
然后重写验证器:
public class ItemListValidator : AbstractValidator<ItemListModel> { public ItemListValidator() { RuleFor(model => model.Items) .NotNull() .Must(items => items.Any()) .WithMessage("列表至少要有一个项目"); RuleForEach(model => model.Items) .SetValidator(new ItemValidator()); } }
临时替代方案(不推荐)
如果不想新建包装类,也可以把IEnumerable<Item>转成List<Item>来绕开索引器问题,但这种方式会额外生成集合副本,且错误信息的属性路径不够直观:
public class ItemListValidator : AbstractValidator<IEnumerable<Item>> { public ItemListValidator() { RuleFor(items => items) .NotNull() .Must(items => items.Any()) .WithMessage("列表至少要有一个项目"); RuleForEach(items => items.ToList()) .SetValidator(new ItemValidator()); } }
为什么包装类方案更好
用包装类的话,FluentValidation能正确识别Items这个属性,生成的错误信息会带上元素索引(比如Items[0].Name不能为空),调试和定位问题更方便,也更符合后续扩展需求。
内容的提问来源于stack exchange,提问作者BASKA
相关产品推荐
相关产品推荐

