• .net core 数据统一响应分享


    前言

    代码胡乱写,维护火葬场!

    在平时工作中遇到前同事写接口这样返回值


    当接口返回1时,不去看他的代码就永远猜不到这个1代表的是返回成功还是返回值

    稍微好点的

    维护和改bug简直让人疯狂,导致大部分时间浪费在“体会”别人返回值的逻辑中

    天天加班与救bug于水火之中

    合理分配前后端返回值很重要!

    一般我们常用统一的格式返回json,无论后台是运行正常还是发生异常,响应给前端的数据格式是不变的!

        public class Result<T> where T : class
        {
            public ResultCode code { get; set; }
    
            public string msg { get; set; }
    
            public T data { get; set; }
        }
    

    包装一下,通常使用构造函数

        public class Result<T> where T : class
        {
            public ResultCode code { get; set; }
    
            public string msg { get; set; }
    
            public T data { get; set; }
    
            public Result(T data)
            {
                code = ResultCode.Ok;
                msg = ResultCode.Ok.GetDescription();
                this.data = data;
            }
    
            public Result(ResultCode code, string msg, T data)
            {
                this.code = code;
                this.msg = msg ?? code.GetDescription();
                this.data = data;
            }
        }
    

    这么使用new Result<Store>(code, msg, data)使用起来还是不够简化
    继续封装

        public class Result<T> where T : class
        {
            public ResultCode code { get; set; }
    
            public string msg { get; set; }
    
            public T data { get; set; }
    
            public Result(T data)
            {
                code = ResultCode.Ok;
                msg = ResultCode.Ok.GetDescription();
                this.data = data;
            }
    
            public Result(ResultCode code, string msg, T data)
            {
                this.code = code;
                this.msg = msg ?? code.GetDescription();
                this.data = data;
            }
    
            public static Result<T> FromCode(ResultCode code, string msg = null, T data = default)
            {
                if (data == null)
                    data = (T) new Object();
                return new Result<T>(code, msg, data);
            }
    
            public static Result<T> Ok(T data)
            {
                return new Result<T>(data);
            }
    
            public static Result<T> FromError(ResultCode code = ResultCode.Fail, string msg = null, T data = default)
            {
                return new Result<T>(code, msg, data);
            }
        }
    
            [HttpGet]
            public Result<Store> Get()
            {
                return Result<Store>.Ok(new Store());
            }
    

    这样就稍微好点了

    全局处理响应数据

    虽然控制器返回值可以统一了,但是异常处理并没有统一,这时候就需要建个中间件/异常过滤器进行处理异常

        app.UseMiddleware<GlobalExceptionHandlerMiddleware>();
        public class GlobalExceptionHandlerMiddleware
        {
            private readonly RequestDelegate _next;
    
            public GlobalExceptionHandlerMiddleware(RequestDelegate next)
            {
                _next = next;
            }
    
            public async Task Invoke(HttpContext context)
            {
                try
                {
                    await _next(context);
                }
                catch (System.Exception ex)
                {
                    context.Response.StatusCode = 500;
                    context.Response.ContentType = "text/json;charset=utf-8;";
    
                    if (ex is ResultException == false)
                    {
                        var logger = context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger<GlobalExceptionHandlerMiddleware>();
                        logger.LogError(1, ex, ex.Message);
                    }
    
                    var json = Result<object>.FromCode(ResultCode.Fail, ex.Message);
                    var error = JsonSerializer.Serialize(json);
    
                    await context.Response.WriteAsync(error);
                }
            }
        }
    

    有些异常是不需要记录的,这时候可以自定义ResultException进行判断

        public class ResultException : Exception
        {
            public ResultException(string message) : base(message)
            {
            }
    
            public ResultException(string message, Exception e) : base(message, e)
            {
    
            }
        }
    
                    if (ex is ResultException == false)
                    {
                        var logger = context.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger<GlobalExceptionHandlerMiddleware>();
                        logger.LogError(1, ex, ex.Message);
                    }
    

    参数校验处理

    一个接口一般对参数(请求数据)都会进行安全校验,按照之前的格式返回验证异常。

        public class ModelActionFilter : ActionFilterAttribute, IActionFilter
        {
            public override void OnActionExecuting(ActionExecutingContext context)
            {
                if (!context.ModelState.IsValid)
                {
                    var errorResults = new List<ErrorResultDto>();
                    foreach (var item in context.ModelState)
                    {
                        var result = new ErrorResultDto
                        {
                            Field = item.Key,
                            Msg = "",
                        };
                        foreach (var error in item.Value.Errors)
                        {
                            if (!string.IsNullOrEmpty(result.Msg))
                            {
                                result.Msg += '|';
                            }
                            result.Msg += error.ErrorMessage;
                        }
                        errorResults.Add(result);
                    }
                    context.Result = new JsonResult(Result<List<ErrorResultDto>>.FromCode(ResultCode.InvalidData, data: errorResults));
                }
            }
        }
    
        public class ErrorResultDto
        {
            /// <summary>
            /// 参数领域
            /// </summary>
            public string Field { get; set; }
    
            /// <summary>
            /// 错误信息
            /// </summary>
            public string Msg { get; set; }
        }
    

    Startup.cs

                services.AddControllers(options =>
                {
                    options.Filters.Add(new ModelActionFilter());
                    options.MaxModelValidationErrors = 50;
                    options.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor(
                        _ => "该字段不可为空。");
                })
                .ConfigureApiBehaviorOptions(options =>
                {
                    options.SuppressModelStateInvalidFilter = true;
                })
    
  • 相关阅读:
    WinForm------GridControl添加底部合计框
    WinForm------如何将GridControl数据导出到Excel
    C#------DateTime自定义格式
    WinForm------RepositoryItemCheckEdit属性介绍
    C#之设计模式之六大原则(转载)
    C#委托的介绍(delegate、Action、Func、predicate)
    ·c#之Thread实现暂停继续(转)
    支持取消操作和暂停操作的Backgroundworker
    C#之Winform跨线程访问控件
    C#在使用Assembly加载程序集时失败
  • 原文地址:https://www.cnblogs.com/WNpursue/p/12693466.html
Copyright © 2020-2023  润新知