前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebApi 统一封装返回结果+全局异常处理

WebApi 统一封装返回结果+全局异常处理

作者头像
郑子铭
发布2023-12-26 19:07:26
2800
发布2023-12-26 19:07:26
举报

统一封装返回结果

使用一个枚举类封装一下常用的业务代码

代码语言:javascript
复制
public enum ResultCode
{
    [Description("操作失败!")]
    Fail = 10000,
    [Description("请求成功!")]
    Success = 20000
}

我又想要能够在返回状态码的时候能够附带着返回一下对应的Descrioption,所以定义一个静态类,用于获取enum类上的Description特性

代码语言:javascript
复制
public static class EnumHelper
{
    // 获取枚举类型的所有值和它们的描述
    public static Dictionary<T, string> GetDescriptions<T>() where T : Enum
    {
        var descriptions = new Dictionary<T, string>();

        foreach (var value in Enum.GetValues(typeof(T)).Cast<T>())
        {
            var fieldInfo = typeof(T).GetField(value.ToString());
            var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(
                typeof(DescriptionAttribute), false);
            descriptions[value] = attributes.Length > 0 ? attributes[0].Description : value.ToString();
        }

        return descriptions;
    }
}

现在来定义要返回的JsonResult类

代码语言:javascript
复制
public class JsonResult
{
    public bool Success { get; set; }
    public int Code { get; set; }
    public string? Msg { get; set; }
    public Object? Data { get; set; }

    public JsonResult(){}
    public JsonResult(bool success)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)ResultCode.Fail;
        Msg = ResultTool.DescriptionsDictionary[(ResultCode)Code];
    }

    
    public JsonResult(bool success, string msg)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)ResultCode.Fail;
        Msg = msg;
    }

    public JsonResult(bool success, ResultCode resultEnum)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)resultEnum;
        Msg = ResultTool.DescriptionsDictionary[(ResultCode)Code];
    }

    public JsonResult(bool success, Object data)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)ResultCode.Fail;
        Msg = ResultTool.DescriptionsDictionary[(ResultCode)Code];
        Data = data;
    }

    public JsonResult(bool success, ResultCode resultEnum, Object data)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)resultEnum;
        Msg = ResultTool.DescriptionsDictionary[(ResultCode)Code];
        Data = data;
    }

    public JsonResult(bool success, ResultCode resultEnum, string msg)
    {
        Success = success;
        Code = success ? (int)ResultCode.Success : (int)resultEnum;
        this.Msg = msg;
    }
    
}

使用ResultTool快速构建一个JsonResult类

代码语言:javascript
复制
public static class ResultTool
{
    public static Dictionary<ResultCode, string> DescriptionsDictionary = EnumHelper.GetDescriptions<ResultCode>();
    
    
    public static JsonResult Success()
    {
        return new JsonResult(true);
    }

    public static JsonResult Success(Object data)
    {
        return new JsonResult(true, data);
    }

    public static JsonResult Fail()
    {
        return new JsonResult(false);
    }

    public static JsonResult Fail(ResultCode resultCode)
    {
        return new JsonResult(false, resultCode);
    }

    public static JsonResult Fail(ResultCode resultCode, string msg)
    {
        return new JsonResult(false, resultCode, msg);
    }

    public static JsonResult Fail(string msg)
    {
        return new JsonResult(false, msg);
    }

    public static JsonResult Fail(bool b, ResultCode resultCode, string message)
    {
        return new JsonResult(false, resultCode, message);
    }
}

现在去Controlle中尝试下

代码语言:javascript
复制
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet(Name = "GetWeatherForecast")]
    public JsonResult Get()
    {
        var MyList = Enumerable.Range(1, 2).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        return ResultTool.Success(MyList);
    }
}

现在能够正确的返回我想要的格式。有很多大佬使用了中间件或者过滤器来实现统一封装返回结果,我个人感觉我这种方式比较简单,也比较便于理解。

全局异常处理

程序运行时难免出现异常情况,有时候是我们手动抛出业务异常返回给前端,比如删除的字段前端没有传给我们导致的异常。我们手动抛出一个异常试一下。

尝试对异常进行处理,也能够返回对应的JsonResult。首先定义一个BusinessException继承Exception。

代码语言:javascript
复制
public class BusinessException : Exception
{
    public ResultCode ErrorCode { get; set; }

    public BusinessException(string message) : base(message)
    {
        ErrorCode = ResultCode.Fail;
    }

    public BusinessException(ResultCode errorCode, string message) : base(message)
    {
        this.ErrorCode = errorCode;
    }
}

然后定义一个中间件,以便捕获程序运行中的异常。

代码语言:javascript
复制
public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionHandlerMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private static Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.OK;

        JsonResult result;

        if (exception is BusinessException businessException)
        {
            // BusinessException处理
            result = ResultTool.Fail(businessException.ErrorCode, businessException.Message);
        }
        else
        {
            // 其他未处理异常处理
            // result = ResultTool.Fail(ResultCode.Fail, exception.Message);
            result = ResultTool.Fail(ResultCode.Fail, "系统异常!");
        }

        return context.Response.WriteAsJsonAsync(result);
    }
}

然后在Program.cs中添加这个中间件,全局异常中间件处理应该尽可能的靠前,这样才能够捕获尽可能多的异常。

代码语言:javascript
复制
app.UseMiddleware<ExceptionHandlerMiddleware>();

手动抛一个异常试试

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-12-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DotNet NB 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 统一封装返回结果
  • 全局异常处理
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档