.net core 数据统一响应分享
程序员文章站
2022-05-18 19:08:15
前言 代码胡乱写,维护火葬场! 在平时工作中遇到前同事写接口这样返回值 当接口返回1时,不去看他的代码就永远猜不到这个1代表的是返回成功还是返回值 稍微好点的 维护和改bug简直让人疯狂,导致大部分时间浪费在“体会”别人返回值的逻辑中 天天加班与救bug于水火之中 合理分配前后端返回值很重要! 一般 ......
前言
代码胡乱写,维护火葬场!
在平时工作中遇到前同事写接口这样返回值
当接口返回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( _ => "该字段不可为空。"); })
推荐阅读
-
详解ASP.NET Core实现强类型Configuration读取配置数据
-
.NET Core Dapper操作mysql数据库的实现方法
-
.NET Core 获取数据库上下文实例的方法和配置连接字符串
-
干货分享:ASP.NET CORE(C#)与Spring Boot MVC(JAVA)异曲同工的编程方式总结
-
.NET Core开发的iNeuOS工业互联网平台,发布 iNeuDA 数据分析展示组件,快捷开发图形报表和数据大屏
-
.NET Core开发的iNeuOS工业互联平台,升级四大特性:配置数据接口、图元绑定数据、预警配置和自定义菜单
-
ASP.NET Core & 双因素验证2FA 实战经验分享
-
.Net Core API使用ODP.NET操作Oracle数据库
-
汇总:ASP.NET Core中HttpContext获取传参数据,有哪些方式
-
.NET Core WebApi中如何实现多态数据绑定实例代码