欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.net core 数据统一响应分享

程序员文章站 2022-05-18 19:08:15
前言 代码胡乱写,维护火葬场! 在平时工作中遇到前同事写接口这样返回值 当接口返回1时,不去看他的代码就永远猜不到这个1代表的是返回成功还是返回值 稍微好点的 维护和改bug简直让人疯狂,导致大部分时间浪费在“体会”别人返回值的逻辑中 天天加班与救bug于水火之中 合理分配前后端返回值很重要! 一般 ......

前言

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

在平时工作中遇到前同事写接口这样返回值
.net core 数据统一响应分享
.net core 数据统一响应分享
当接口返回1时,不去看他的代码就永远猜不到这个1代表的是返回成功还是返回值

稍微好点的
.net core 数据统一响应分享
维护和改bug简直让人疯狂,导致大部分时间浪费在“体会”别人返回值的逻辑中

天天加班与救bug于水火之中
.net core 数据统一响应分享

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

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

    public class result<t> where t : class
    {
        public resultcode code { get; set; }

        public string msg { get; set; }

        public t data { get; set; }
    }

.net core 数据统一响应分享

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

    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(
                    _ => "该字段不可为空。");
            })