Asp.Net Core WebApi统一封装返回结果
一般来说,WebApi返回数据需要封装为固定格式,比如state、message、data三个属性,state返回状态,为true或false(也可用status返回状态码),message返回消息,如操作失败的异常信息,data用来返回操作结果。
/// <summary> /// 操作结果封装 /// </summary> public class OperateResult { /// <summary> /// 状态 /// </summary> public bool State { get; set; } /// <summary> /// 消息 /// </summary> public string Message { get; set; } /// <summary> /// 操作结果 /// </summary> public object Data { get; set; } /// <summary> /// 初始化 /// </summary> /// <param name="state">状态</param> /// <param name="message">消息</param> /// <param name="data">操作结果</param> public OperateResult(bool state, string message, object data = null) { this.State = state; this.Message = message; this.Data = data; } }
定义用户异常,对用户友好异常和系统异常进行区分,参数验证失败、资源未找到或其他逻辑性错误均抛出用户异常。
/// <summary> /// 用户友好异常 /// </summary> public class UserFriendlyException : Exception { public UserFriendlyException(string message) : base(message) { } }
使用方法过滤器拦截请求响应,在方法执行后对返回结果进行统一封装:
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Filters; using Serilog; using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WebApi { /// <summary> /// 方法过滤器 /// </summary> public class ActionFilter : IActionFilter { /// <summary> /// 监控日志 /// </summary> public static ILogger LoggerMonitor { get; set; } /// <summary> /// 错误日志 /// </summary> public static ILogger LoggerError { get; set; } /// <summary> /// 创建请求日志文本 /// </summary> /// <param name="method">请求方法</param> /// <param name="controllerName">控制器名称</param> /// <param name="actionName">方法名称</param> /// <param name="actionArgs">方法参数</param> /// <returns></returns> private string CreateRequestLogText(string method, string controllerName, string actionName, IDictionary<string, object> actionArgs) { StringBuilder sb = new StringBuilder(); sb.AppendLine($"收到请求[{method}]/{controllerName}/{actionName},参数:"); if (actionArgs.Count > 0) { foreach (var p in actionArgs) { sb.AppendLine($" " + p.Key + ":" + Newtonsoft.Json.JsonConvert.SerializeObject(p.Value)); } } else { sb.AppendLine(" 无"); } return sb.ToString(); } /// <summary> /// 创建响应日志文本 /// </summary> /// <param name="method">请求方法</param> /// <param name="controllerName">控制器名称</param> /// <param name="actionName">方法名称</param> /// <param name="result">执行结果</param> /// <returns></returns> private string CreateResponseLogText(string method, string controllerName, string actionName, object result) { StringBuilder sb = new StringBuilder(); sb.AppendLine($"完成请求[{method}]/{controllerName}/{actionName},结果:"); if (result != null) { sb.AppendLine(" " + Newtonsoft.Json.JsonConvert.SerializeObject(result)); } else { sb.AppendLine(" 无"); } return sb.ToString(); } /// <summary> /// 方法执行前 /// </summary> /// <param name="context"></param> public void OnActionExecuting(ActionExecutingContext context) { if (LoggerMonitor != null) { // 记录请求参数日志 ControllerActionDescriptor desc = context.ActionDescriptor as ControllerActionDescriptor; if (desc != null) { var logText = CreateRequestLogText( context.HttpContext.Request.Method, desc.ControllerName, desc.ActionName, context.ActionArguments); LoggerMonitor.Debug(logText); } } } /// <summary> /// 方法执行后 /// </summary> /// <param name="context"></param> public void OnActionExecuted(ActionExecutedContext context) { ObjectResult rst = context.Result as ObjectResult; object rstValue = rst != null ? rst.Value : null; if (context.Exception != null) { // 异常处理 context.ExceptionHandled = true; if (context.Exception is UserFriendlyException) { // 如果是用户异常 context.HttpContext.Response.StatusCode = 200; context.Result = new ObjectResult(new OperateResult(false, context.Exception.Message, rstValue)); } else { // 如果是系统异常,禁止返回异常的详细信息 context.HttpContext.Response.StatusCode = 500; context.Result = new ContentResult() { Content = context.Exception.Message }; if (LoggerError != null) { LoggerError.Error(context.Exception, context.Exception.Message); } } } else { // 无异常 context.Result = new ObjectResult(new OperateResult(true, string.Empty, rstValue)); } if (LoggerMonitor != null) { // 记录请求结果日志 ControllerActionDescriptor desc = context.ActionDescriptor as ControllerActionDescriptor; if (desc != null) { var logText = CreateResponseLogText( context.HttpContext.Request.Method, desc.ControllerName, desc.ActionName, rstValue); LoggerMonitor.Debug(logText); } } } } }
在Startup类的ConfigureServices方法中启用方法过滤器:
services.AddMvc(options => { options.Filters.Add(typeof(ActionFilter)); });
至此,所有WebApi方法的返回结果均被统一封装,操作正常返回state为true,data为操作结果,用户异常返回state为false,message中为错误信息,系统异常返回Http状态码500,content为异常信息。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!