900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值 模型验证 异常)

ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值 模型验证 异常)

时间:2019-04-23 00:16:11

相关推荐

ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值 模型验证 异常)

现阶段,基本上都是前后端分离项目,这样一来,就需要前后端配合,没有统一返回格式,那么对接起来会很麻烦,浪费时间。我们需要把所有接口及异常错误信息都返回一定的Json格式,有利于前端处理,从而提高了工作效率。

一、准备工作

定义响应实体类

/// <summary> /// 响应实体类 /// </summary> public class ResultModel { /// <summary> /// 状态码 /// </summary> public int ReturnCode { get; set; } /// <summary> /// 内容 /// </summary> public object Data { get; set; } /// <summary> /// 错误信息 /// </summary> public string ErrorMessage { get; set; } /// <summary> /// 是否成功 /// </summary> public bool IsSuccess { get; set; } }

修改Controller层

在controller层处理业务请求,new 一个ResultModel 对象,返回给前端。

/// <summary> /// 查询用户 /// </summary> /// <returns></returns> [Route("getUser")] [HttpGet] public ResultModel GetUser() { var data = _userRepository.GetAll().ToList(); return new ResultModel() { Data = data, ErrorMessage = null, IsSuccess = true, ReturnCode = 200 }; }

这样需要每个方法都需要重新new一个ResultModel 对象,感觉有点代码冗余。

我们只需要加几个静态方法,每个方法返回都是ResultModel对象,成功的时候调用ResultModel.OK,失败的时候调用ResultModel.ERROR即可。

优化

添加两个静态方法

/// <summary> /// 成功 /// </summary> /// <param name="data">返回数据</param> /// <returns></returns> public static ResultModel Ok(object data) { return new ResultModel { Data = data, ErrorMessage = null, IsSuccess = true, ReturnCode = 200 }; } /// <summary> /// 失败 /// </summary> /// <param name="str">错误信息</param> /// <param name="code">状态码</param> /// <returns></returns> public static ResultModel Error(string str,int code) { return new ResultModel { Data = null, ErrorMessage = str, IsSuccess = false, ReturnCode = code }; }

修改控制器

/// <summary> /// 查询用户 /// </summary> /// <returns></returns> [Route("getUser")] [HttpGet] public ResultModel GetUser() { var data = _userRepository.GetAll().ToList(); return ResultModel.Ok(data); }

二、全局异常处理

通过全局异常处理,任何错误信息都会被拦截,返回统一格式。

定义全局异常处理中间件

using System;using System.Threading.Tasks;using Microsoft.AspNetCore.Http;using NetCoreWebApi.Util;using Newtonsoft.Json;namespace NetCoreWebApi.Filter{ /// <summary> /// 处理全局信息中间件 /// </summary> public class ExceptionMiddleWare { /// <summary> /// 处理HTTP请求的函数。 /// </summary> private readonly RequestDelegate _next; /// <summary> /// 构造函数 /// </summary> /// <param name="next"></param> public ExceptionMiddleWare(RequestDelegate next) { _next = next; } public async Task Invoke(HttpContext context) { try { //抛给下一个中间件 await _next(context); } catch (Exception ex) { await WriteExceptionAsync(context, ex); } finally { await WriteExceptionAsync(context, null); } } private async Task WriteExceptionAsync(HttpContext context, Exception exception) { if (exception != null) { var response = context.Response; var message = exception.InnerException == null ? exception.Message : exception.InnerException.Message; response.ContentType = "application/json"; await response.WriteAsync(JsonConvert.SerializeObject(ResultModel.Error(message, 400))).ConfigureAwait(false); } else { var code = context.Response.StatusCode; switch (code) { case 200: return; case 204: return; case 401: context.Response.ContentType = "application/json"; await context.Response.WriteAsync(JsonConvert.SerializeObject(ResultModel.Error("token已过期,请重新登录.", code))).ConfigureAwait(false); break; default: context.Response.ContentType = "application/json"; await context.Response.WriteAsync(JsonConvert.SerializeObject(ResultModel.Error("未知错误", code))).ConfigureAwait(false); break; } } } }}

注册中间件

在Startup.cs启动类的Configure方法中添加UseMiddleware方法

//异常处理中间件 app.UseMiddleware(typeof(ExceptionMiddleWare));

三、验证实体模型

有两种方式:

1.使用自定义过滤器

2.使用默认自带的400模型验证,需要在控制器上面加上【ApiController】,这种方式优先级比较高,如果需要自定义模型验证,则需要先关闭默认的模型验证

【ApiController】

自动推断参数绑定:可以省略[FromBody]等参数特性

自动模型验证:自动验证模型是否合法

参考:/sD7O95O/article/details/81844154

services.AddMvc(e => { e.Filters.Add<CheckModel>(); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .ConfigureApiBehaviorOptions(e => { //关闭默认模型验证 e.SuppressModelStateInvalidFilter = true; });

参考:/zh-cn/dotnet/api/microsoft.aspnetcore.mvc.apibehavioroptions?view=aspnetcore-2.2

自定义过滤器

创建CheckModel过滤器继承ActionFilterAttribute抽象类,重写其中需要的方法

using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Filters;using NetCoreWebApi.Util;namespace NetCoreWebApi.Filter{ /// <summary> /// 验证实体对象是否合法 /// </summary> public class CheckModel : ActionFilterAttribute { /// <summary> /// Action 调用前执行 /// </summary> /// <param name="actionContext"></param> public override void OnActionExecuting(ActionExecutingContext actionContext) { if (!actionContext.ModelState.IsValid) { //初始化返回结果 var result = new ResultModel { IsSuccess = false, ReturnCode = 400 }; foreach (var item in actionContext.ModelState.Values) { foreach (var error in item.Errors) { result.ErrorMessage += error.ErrorMessage + "|"; } } actionContext.Result = new JsonResult(result); } } /// <summary> /// Action 方法调用后,Result 方法调用前执行 /// </summary> /// <param name="context"></param> public override void OnActionExecuted(ActionExecutedContext context) {

} }}

将写的过滤器注册到全局

services.AddMvc(e => { //注册过滤器 e.Filters.Add<CheckModel>(); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .ConfigureApiBehaviorOptions(e => { //关闭默认模型验证 e.SuppressModelStateInvalidFilter = true; });

创建UserDto

using ponentModel.DataAnnotations;namespace NetCoreWebApi.Repository.Dto{ /// <summary> /// 用户传输对象 /// </summary> public class UserDto { /// <summary> /// 用户Id /// </summary> [StringLength(32, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "用户Id")] public string UserId { get; set; } /// <summary> /// 用户名 /// </summary> [StringLength(20, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "用户名")] public string UserName { get; set; } /// <summary> /// 邮箱 /// </summary> [StringLength(30, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "邮箱")] public string Email { get; set; } }}

测试

默认模型验证

services.AddMvc(e => { //注册过滤器 //e.Filters.Add<CheckModel>(); }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .ConfigureApiBehaviorOptions(e => { ////关闭默认模型验证 //e.SuppressModelStateInvalidFilter = true; e.InvalidModelStateResponseFactory = actionContext => { //获取验证失败的模型字段 var errors = actionContext.ModelState .Where(e1 => e1.Value.Errors.Count > 0) .Select(e1 => e1.Value.Errors.First().ErrorMessage) .ToList(); var str = string.Join("|", errors); return new JsonResult(ResultModel.Error(str, 400)); }; });

两种验证方法效果是一致的

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。