.NET 7中自定义ExceptionFilter遇模型验证错误时被跳过的问题
解决.NET 7中自定义ExceptionFilterAttribute不处理模型验证错误的问题
问题原因
ASP.NET Core的模型验证在Action执行前完成,默认情况下验证失败时,框架会直接返回标准400响应,不会抛出异常,因此你的ExceptionFilterAttribute的OnException方法不会被触发——因为没有异常发生。
解决方案
有两种常用方案可以实现自定义处理模型验证错误的需求:
方案1:禁用默认模型验证响应,让验证失败抛出异常
通过禁用框架自带的模型验证响应过滤器,让模型验证失败时抛出异常,这样你的ExceptionFilterAttribute就能捕获并处理。
- 修改服务注册代码:
services.AddControllers(options => { options.Filters.Add<ApiExceptionFilterAttribute>(); // 禁用默认的模型验证自动响应过滤器 options.SuppressModelStateInvalidFilter = true; });
- 在
ApiExceptionFilterAttribute中处理模型验证相关异常:
public class ApiExceptionFilterAttribute : ExceptionFilterAttribute { public override void OnException(ExceptionContext context) { // 处理模型验证失败抛出的异常 if (context.Exception is InvalidOperationException) { var modelState = context.HttpContext.Features.Get<IModelStateFeature>()?.ModelState; var errors = modelState? .Where(x => x.Value.Errors.Any()) .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray() ); // 构建自定义响应 var response = new { StatusCode = 400, Message = "模型验证失败", Errors = errors }; context.Result = new JsonResult(response) { StatusCode = StatusCodes.Status400BadRequest }; context.ExceptionHandled = true; return; } // 处理其他异常逻辑 // ... } }
方案2:实现专门的模型验证过滤器(推荐)
ASP.NET Core提供了IInvalidModelStateResponseFilter接口,专门用于自定义模型验证失败的响应,这种方式更符合框架设计,无需修改异常处理逻辑。
- 创建自定义模型验证过滤器:
public class CustomModelValidationFilter : IInvalidModelStateResponseFilter { public void OnInvalidModelState(ActionExecutingContext context) { // 提取验证错误信息 var errors = context.ModelState .Where(x => x.Value.Errors.Any()) .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Errors.Select(e => e.ErrorMessage).ToArray() ); // 构建自定义响应(可与ExceptionFilter输出格式保持一致) var response = new { StatusCode = 400, Message = "One or more validation errors occurred.", Errors = errors }; context.Result = new JsonResult(response) { StatusCode = StatusCodes.Status400BadRequest }; } }
- 注册过滤器:
services.AddControllers(options => { options.Filters.Add<ApiExceptionFilterAttribute>(); }) .AddMvcOptions(options => { // 添加自定义模型验证过滤器 options.Filters.Add<CustomModelValidationFilter>(); });
方案对比
- 方案1适合希望用同一个过滤器统一处理所有错误(异常+模型验证)的场景,但本质是把模型验证错误转为异常处理,略显牵强。
- 方案2是框架推荐的方式,专门处理模型验证错误,逻辑更清晰,与异常处理解耦。
内容的提问来源于stack exchange,提问作者Mugen
相关产品推荐
相关产品推荐

