标签:验证 静态方法 mode 后端 break mod finally 优化 returns
现阶段,基本上都是前后端分离项目,这样一来,就需要前后端配合,没有统一返回格式,那么对接起来会很麻烦,浪费时间。我们需要把所有接口及异常错误信息都返回一定的Json格式,有利于前端处理,从而提高了工作效率。
一、准备工作
定义响应实体类
///
/// 响应实体类
///
public class ResultModel
{
///
/// 状态码
///
public int ReturnCode { get; set; }
///
/// 内容
///
public object Data { get; set; }
///
/// 错误信息
///
public string ErrorMessage { get; set; }
///
/// 是否成功
///
public bool IsSuccess { get; set; }
}
修改Controller层
在controller层处理业务请求,new 一个ResultModel 对象,返回给前端。
///
/// 查询用户
///
///
[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即可。
优化
添加两个静态方法
///
/// 成功
///
/// 返回数据
///
public static ResultModel Ok(object data)
{
return new ResultModel { Data = data, ErrorMessage = null, IsSuccess = true, ReturnCode = 200 };
}
///
/// 失败
///
/// 错误信息
/// 状态码
///
public static ResultModel Error(string str,int code)
{
return new ResultModel { Data = null, ErrorMessage = str, IsSuccess = false, ReturnCode = code };
}
修改控制器
///
/// 查询用户
///
///
[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
{
///
/// 处理全局信息中间件
///
public class ExceptionMiddleWare
{
///
/// 处理HTTP请求的函数。
///
private readonly RequestDelegate _next;
///
/// 构造函数
///
///
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]等参数特性
自动模型验证:自动验证模型是否合法
参考:https://blog.csdn.net/sD7O95O/article/details/81844154
services.AddMvc(e =>
{
e.Filters.Add();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(e =>
{
//关闭默认模型验证
e.SuppressModelStateInvalidFilter = true;
});
参考:https://docs.microsoft.com/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
{
///
/// 验证实体对象是否合法
///
public class CheckModel : ActionFilterAttribute
{
///
/// Action 调用前执行
///
///
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 BadRequestObjectResult(result);
}
}
///
/// Action 方法调用后,Result 方法调用前执行
///
///
public override void OnActionExecuted(ActionExecutedContext context)
{
}
}
}
将写的过滤器注册到全局
services.AddMvc(e =>
{
//注册过滤器
e.Filters.Add();
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.ConfigureApiBehaviorOptions(e =>
{
//关闭默认模型验证
e.SuppressModelStateInvalidFilter = true;
});
创建UserDto
using System.ComponentModel.DataAnnotations;
namespace NetCoreWebApi.Repository.Dto
{
///
/// 用户传输对象
///
public class UserDto
{
///
/// 用户Id
///
[StringLength(32, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "用户Id")]
public string UserId { get; set; }
///
/// 用户名
///
[StringLength(20, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "用户名")]
public string UserName { get; set; }
///
/// 邮箱
///
[StringLength(30, ErrorMessage = "{0}最多{1}个字符"), Display(Name = "邮箱")]
public string Email { get; set; }
}
}
测试
默认模型验证
services.AddMvc(e =>
{
//注册过滤器
e.Filters.Add();
})
.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 BadRequestObjectResult(ResultModel.Error(str, 400));
};
});
两种验证方法效果是一致的
ASP.NET Core 2.2 WebApi 系列【八】统一返回格式(返回值、模型验证、异常)
标签:验证 静态方法 mode 后端 break mod finally 优化 returns
原文地址:https://www.cnblogs.com/tenghao510/p/11927930.html