参考:

  • https://code-maze.com/action-filters-aspnetcore/
  • https://github.com/aspnet/AspNetCore.Docs/issues/12157
  • https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-3.0#automatic-http-400-responses
  1. 关闭默认模型验证过滤器
    [ApiController] 默认自带有 400 模型验证,且优先级比较高,如果需要自定义模型验证,则需要先关闭默认的模型验证
    在 StartUp.cs 中的 MVC 服务配置修改

    #region MVC
    services.AddMvc(o =>
    {
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
    .ConfigureApiBehaviorOptions(o =>
    {
        o.SuppressModelStateInvalidFilter = true;
    });
    #endregion
  2. 首先定义统一输出的格式为

    n
    {
        "code": "",
        "errors":[
          {
            "filed":"",
            "message":""
        	}
        ]
    }
  3. 添加自定义模型验证 DTO

    public class ErrorResultDTO
    {
        /// <summary>
        /// 参数领域
        /// </summary>
        public string Field { get; set; }
        /// <summary>
        /// 错误信息
        /// </summary>
        public string Message { get; set; }   
    }
  4. 添加过滤器
    过滤器继承自:ActionFilterAttribute, IActionFilter

    public class ModelActionFiter :ActionFilterAttribute, IActionFilter
    {
        public ModelActionFiter()
        {
        }
      
        public override void OnActionExecuted(ActionExecutedContext context)
        {
        }
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {     
                List<ErrorResultDTO> errorResults = new List<ErrorResultDTO>();
                foreach (var item in context.ModelState)
                {
                    var result = new ErrorResultDTO
                    {
                        Field = item.Key,
                        Msg = "",
                    };
                    foreach (var error in item.Value.Errors)
                    {
                        if (!string.IsNullOrEmpty(result.Msg))
                        {
                            result.Msg += '|';
                        }
                        result.Msg += error.ErrorMessage;
                    }
                    errorResults.Add(result);
                }
                context.Result = new BadRequestObjectResult(new
                {
                    Code = StatusCodes.Status400BadRequest,
                   Errors = errorResults
                });  
            }
        }
    }
  5. 将写的过滤器注册到全局

    services.AddMvc(o =>
    {
        o.Filters.Add(new ModelActionFiter());
    })
  6. 结果测试

  7. 扩展

    • 利用拦截器来测试 action 的运行时间,记录日志,并设置时间限制,超过某个时间段自动发送邮件通知维护人员
更新于 阅读次数