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为异常信息。

posted @ 2022-04-26 16:13  广阔之海  阅读(2131)  评论(0编辑  收藏  举报