WebApi接口返回结果及自定义异常封装

3 篇文章 1 订阅

一、接口返回类型封装原因

对接口返回的数据格式进行封装,使开发只关注业务,减少数据格式转换
1.异常结果:可通过自定义异常抛出异常码和异常原因
2.数据结果:接口在返回结果时,自动封装

二、通过扩展MVC的ActionFilterAttribute方法来现实封装

1、扩展类实现

  public class ApiResultFilterAttribute : ActionFilterAttribute
  {
      public override void OnActionExecuted(ActionExecutedContext context)
      {
          if (context.Exception != null)
          {
              // 如果有异常,处理异常并封装响应  
              if (context.Exception is BusExpection expection)
              {
                  context.Result = new ObjectResult(ApiResponse.NoContent(expection.ErrorCode(), expection.ErrorMsg()));
              }
              else
              {
                  context.Result = new ObjectResult(ApiResponse.NoContent(ApiErrorCode.发生异常, context.Exception.Message));
              }

              context.ExceptionHandled = true; // 标记异常已处理  
          }
          else if (context.Result is ObjectResult objectResult)
          {
              // 如果没有异常,封装正常的响应  
              context.Result = new ObjectResult(new ApiResponse() { Code = CommonErrorMsg.成功.GetValue(), Message = CommonErrorMsg.成功.GetName(), Result = objectResult.Value });
          }
      }

      public override void OnActionExecuting(ActionExecutingContext context)
      {
          // 在动作执行前可以添加逻辑,但在这个场景下我们不需要  
      }
  }

2、接口固定返回类定义


public class ApiResponse : ApiResponse<object>
{
    public static ApiResponse OK(object result) => OK(result, ApiErrorCode.成功);

    public static ApiResponse OK(object result, ApiErrorCode code) =>
        new() { Result = result, Code = (int)code, Message = code.ToString() };

    public static ApiResponse NoContent() => NoContent(ApiErrorCode.成功);
    public static ApiResponse NoContent(ApiErrorCode code) => NoContent(code, code.ToString());

    public static ApiResponse NoContent(ApiErrorCode code, string message) => new ApiResponse
    {
        Code = (int)code,
        Message = message
    };

    public static ApiResponse NoContent(int code, string message) => new ApiResponse
    {
        Code = code,
        Message = message
    };

    public static ApiResponse Error(Exception error) => new ApiResponse
    {
        Code = (int)ApiErrorCode.发生异常,
        Message = error.Message
    };

    public static ApiResponse Error(string errorMessage) => NoContent(ApiErrorCode.发生异常, errorMessage);
}

public class ApiResponse<T>
{
    /// <summary>
    /// 响应code(0则成功,否则失败)
    /// response code(0 is success, otherwise is failure)
    /// </summary>
    [Required]
    public int Code { get; set; } = (int)ApiErrorCode.成功;

    /// <summary>
    /// 响应消息
    /// response message
    /// </summary>
    public string Message { get; set; } = "";

    /// <summary>
    /// 响应结果
    /// response result
    /// </summary>
    public T Result { get; set; }

    public ApiResponse<T> OK(T result) => OK(result, ApiErrorCode.成功);

    public ApiResponse<T> OK(T result, ApiErrorCode code)
    {
        this.Code = (int)code;
        this.Result = result;
        return this;
    }

    public ApiResponse<T> NoContent() => NoContent(ApiErrorCode.成功);
    public ApiResponse<T> NoContent(ApiErrorCode code) => NoContent(code, code.ToString());

    public ApiResponse<T> NoContent(ApiErrorCode code, string message)
    {
        this.Code = (int)code;
        this.Message = message;
        return this;
    }

    public ApiResponse<T> Error(Exception error)
    {
        this.Code = (int)ApiErrorCode.发生异常;
        this.Message = error.Message;
        return this;
    }
}

3、自定义异常信息

    public class BusExpection : Exception
    {
        private readonly string errMsg;
        private readonly int Code;
        public BusExpection (string msg = "",
                                    int code = (int)ApiErrorCode.发生异常) : base(msg)
        {
            errMsg = msg;
            Code = code;
        }

        public string ErrorMsg()
        {
            return errMsg ?? base.Message;
        }
        public int ErrorCode()
        {
            return Code;
        }
    }

4、 定义接口异常枚举

public enum ApiErrorCode
{
    成功 = 0,
    失败 = 10001,
    授权失败 = 10002,
    发生异常 = 10003,
    参数验证错误 = 10004,
    重复操作 = 10005
}

5、接口实现

// 在program.cs里配置全局过滤器
builder.Services.AddControllers(config => { config.Filters.Add(typeof(ApiResultFilterAttribute)); })
    .AddNewtonsoftJson();

只需要在方法上添加[ApiResultFilter]特性。也可以给接口方法所在类添加该特性,扩展会应用该类下所有方法。


      
        [ApiResultFilter]
        public Task<Student> Get(int id)
        {
            //抛出自定义异常错误,可指定错误码和错误信息
            throw new BusExpection("参数异常", 100003);
            return "123";
        }

       [ApiResultFilter]
        public Task<Student> Get(int id)
        {
            //原生异常错误信息,无法指定错误code
            throw new Exception("出错了!");
            return "123";
        }


     [ApiResultFilter]
        public Task<Student> Get(int id)
        {
           
             return new Student() { Name = "姓名1", Money = 123 };
          
        }


6、接口实现注意事项

  • 业务逻辑处理时直接抛出自定义异常,不需要再进行异常处理。
  • 业务处理后的数据集直接通过return 返回,不需要额外封装。

7、效果图

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值