原创

asp.net core 统一模型验证拦截实现

在使用webapi对外提供服务的时候,我们希望提供一个统一的返回值例如 {"code":1,"message":"ok","data":""}。为了解耦会对未处理的异常和模型验证进行统一处理。本文介绍了asp.net core 3.1版本中实现统一模型验证的实现方法。

在asp.net core中的过滤器和framework中的过滤器使用上并没有太大差异。新建过滤器ModelVerificationFilter.cs

public class ModelVerificationFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        if (context.ModelState.IsValid)
        {
            return;
        }

        var errorMessage = context.ModelState
            ?.FirstOrDefault(m => m.Value.ValidationState == ModelValidationState.Invalid).Value
            ?.Errors
            ?.FirstOrDefault()
            ?.ErrorMessage;

        context.HttpContext.Response.StatusCode = (int) HttpStatusCode.BadRequest;
        context.Result = new ObjectResult(new ResponseVm(errorMessage, 400));
    }
}

这里在发现模型验证失败的时候,返回第一个模型验证错误信息,并把http的状态码设置为BadRequest。代码中ResponseVm类是前面提到的统一返回值类型。

public class ResponseVm
{
    public ResponseVm(string message, int code)
    {
        Message = message;
        Code = code;
    }

    public ResponseVm()
    {
        Message = "ok";
        Code = 0;
    }

    /// <summary>
    ///     错误信息
    /// </summary>
    public string Message { get; set; }

    /// <summary>
    ///     错误码
    /// </summary>
    public int Code { get; set; }

    public static ResponseVm Success(string msg = "ok")
    {
        return new ResponseVm(msg, 0);
    }

    public static ResponseVm Failed(string msg = "error", int code = -1)
    {
        return new ResponseVm(msg, code);
    }
}

设置好过滤器之后发现并没有输出我们要求的结果,而是产生了一个系统默认的模型验证错误的返回值。其中Source是我们要验证的字段。

{
  "errors": {
    "Source": [
      "来源 必须在 1 至 2 之间"
    ]
    ...
  },
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "|61e0ca29-42ac2f842289c956."
}

参考官方文档Web API应用-概述-自动 HTTP 400响应一节。

使用 2.1 的兼容性版本时,HTTP 400 响应的默认响应类型为 SerializableError。 下述请求正文是序列化类型的示例:
使用 2.2 或更高版本的兼容性版本时,HTTP 400 响应的默认响应类型为 ValidationProblemDetails。
若要禁用自动 400 行为,请将 SuppressModelStateInvalidFilter 属性设置为 true。 将以下突出显示的代码添加到 Startup.ConfigureServices:

  services.AddControllers()
    .ConfigureApiBehaviorOptions(options =>
    {
        ...
        options.SuppressModelStateInvalidFilter = true;
        ...
    });

按文档修改后,统一模型验证拦截成功。两种方法配置

services.Configure<ApiBehaviorOptions>(o =>
{
    o.SuppressModelStateInvalidFilter = true;
});
services.AddControllers()
    .ConfigureApiBehaviorOptions(opt => opt.SuppressModelStateInvalidFilter = true)

参考:

  1. https://docs.microsoft.com/zh-cn/aspnet/core/web-api/?view=aspnetcore-3.1#automatic-http-400-responses
正文到此结束
该篇文章的评论功能已被站长关闭