ASP.NET Core 2.1 Preview 1验证IValidatableObject时ModelState无效键问题
我之前也碰到过这个棘手的问题——在ASP.NET Core 2.1 Preview 1环境下,当ViewModel实现IValidatableObject返回对象级验证错误时,ModelState里会莫名出现无效的空键,不仅干扰状态判断,还可能导致验证消息无法正常显示。咱们先结合你给出的代码场景来梳理:
问题代码重现
ViewModel代码:
public class SearchViewModel : IValidatableObject { // ...some properties... public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { yield return new ValidationResult("My custom object-level error"); } }
控制器动作:
[HttpPost] public IActionResult Search(SearchViewModel viewModel) { if (!ModelState.IsValid) return View(viewModel); return Content("OK"); }
视图片段:
<form asp-action="Search" method="post"> <div asp-validation-summary="All" class="text-danger"></div> <!-- 其他表单元素 --> <button type="submit">Search</button> </form>
问题根源
这是ASP.NET Core 2.1 Preview 1的一个已知bug:当你返回未指定MemberNames的ValidationResult时,框架无法正确识别这是对象级错误,反而会生成一个空字符串的无效键,导致ModelState中出现异常的无效条目。
解决办法
这里有两个实用的解决方案:
方案1:手动指定对象级错误的MemberNames
修改Validate方法,返回ValidationResult时明确指定MemberNames为string.Empty,告诉框架这是属于模型本身的错误:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { yield return new ValidationResult( "My custom object-level error", new[] { string.Empty } // 明确标记为对象级错误 ); }
这样ModelState就会将错误正确关联到模型,不会再生成无效键。
方案2:升级到ASP.NET Core 2.1后续版本
这个bug在ASP.NET Core 2.1 Preview 2以及正式版中已经被修复,如果项目允许,直接升级框架到正式版是最彻底的解决方式,之后无需手动指定MemberNames也能正常处理对象级验证错误。
额外提示
要在视图中正确显示对象级验证错误,务必确保视图包含asp-validation-summary标签,比如上面代码中的<div asp-validation-summary="All" class="text-danger"></div>,这样才能把对象级错误展示给用户。
内容的提问来源于stack exchange,提问作者Darek

