在ASP.NET (Core)中验证后如何访问ValidationResult对象?
问题描述
我通过实现IValidatableObject接口为模型编写了自定义验证逻辑,代码如下:
public class MyModel : IValidatableObject { public string Name { get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { if (Name == "Foo") { yield return new CustomValidationResult(42, nameof(Name)); } } } public class CustomValidationResult : ValidationResult { public CustomValidationResult(int bar, string memberName) : base("FooBar", new[] { memberName }) { Bar = bar; } public int Bar { get; private set; } }
现在我希望在控制器或者动作过滤器中访问CustomValidationResult对象,比如在下面这个动作过滤器里获取Bar属性的值(也就是42):
public class MyActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { // 如何访问验证结果? // 具体来说,如何在此处获取值'42'? } } }
请问有没有办法实现这个需求?
解决方案
当然可以实现!你需要遍历ModelState中的所有验证错误条目,然后将其中的ValidationResult实例强制转换为你的CustomValidationResult类型,就能拿到Bar属性的值了。
这里有两种常见的场景处理方式,直接上代码:
public class MyActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { // 遍历所有ModelState条目及其错误 foreach (var stateEntry in context.ModelState) { foreach (var error in stateEntry.Value.Errors) { // 场景1:验证结果被包装在ValidationException中 if (error.Exception is ValidationException validationEx && validationEx.ValidationResult is CustomValidationResult customResult) { int targetValue = customResult.Bar; // 这里就是你要的42 // 后续可以根据这个值执行你的业务逻辑 } // 场景2:验证结果直接作为ErrorInfo存在 else if (error.ErrorInfo is CustomValidationResult customResultFromInfo) { int targetValue = customResultFromInfo.Bar; } } } } } }
如果你的验证逻辑只会针对特定字段(比如示例中的Name字段),也可以直接定向查找,不用遍历所有条目,效率更高:
public override void OnActionExecuting(ActionExecutingContext context) { if (!context.ModelState.IsValid) { // 直接定位到Name字段的ModelState if (context.ModelState.TryGetValue(nameof(MyModel.Name), out var nameState)) { foreach (var error in nameState.Errors) { if (error.ErrorInfo is CustomValidationResult customResult) { int barValue = customResult.Bar; // 处理你的逻辑 } } } } }
需要注意的是,不同的验证触发场景下,自定义验证结果的存储位置可能不同(要么在Exception里,要么在ErrorInfo里),所以两种情况最好都做判断,避免遗漏。
内容的提问来源于stack exchange,提问作者turdus-merula
相关产品推荐
相关产品推荐

