在使用webapi对外提供服务的时候,我们希望提供一个统一的返回值例如 {“code”:1,”message”:”ok”,”data”:””}。为了解耦会对未处理的异常和模型验证进行统一处理。本文介绍了asp.net core 3.1版本中实现统一模型验证的实现方法。
在asp.net core中的过滤器和framework中的过滤器使用上并没有太大差异。新建过滤器ModelVerificationFilter.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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类是前面提到的统一返回值类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| 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是我们要验证的字段。
1 2 3 4 5 6 7 8 9 10 11 12
| { "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:
1 2 3 4 5 6 7
| services.AddControllers() .ConfigureApiBehaviorOptions(options => { ... options.SuppressModelStateInvalidFilter = true; ... });
|
按文档修改后,统一模型验证拦截成功。两种方法配置
1 2 3 4
| services.Configure<ApiBehaviorOptions>(o => { o.SuppressModelStateInvalidFilter = true; });
|
1 2
| services.AddControllers() .ConfigureApiBehaviorOptions(opt => opt.SuppressModelStateInvalidFilter = true)
|
参考:
- https://docs.microsoft.com/zh-cn/aspnet/core/web-api/?view=aspnetcore-3.1#automatic-http-400-responses