一.背景
为了方便开发,简化代码,也为了与前端方便对接,需要对接口服务返回结果进行统一处理.
.Net Core 中返回结果的处理与 .Net Framework 中的处理不一样.
.Net Core 返回结果处理继承自 ActionFilterAttribute , OnActionExecuted 的参数为 ActionExecutedContext.
我们需要对之前的处理进行修改.
二.封装
1.首先定义一个统一返回结果类
我们需要定义一个统一返回结果类ReturnObject简写为Robj
约定返回结果Code
1 /// <summary> 2 /// 返回Code 3 /// </summary> 4 public enum RCode 5 { 6 /// <summary> 7 /// 成功 8 /// </summary> 9 [JsonProperty("1000")] 10 Success = 1000, 11 12 /// <summary> 13 /// 登录超时,需重新登录 14 /// </summary> 15 [JsonProperty("2000")] 16 NeedLogin = 2000, 17 18 /// <summary> 19 /// 程序异常 20 /// </summary> 21 [JsonProperty("3000")] 22 Exception = 3000, 23 24 /// <summary> 25 /// 系统错误 26 /// </summary> 27 [JsonProperty("4000")] 28 SysError = 4000 29 }
返回结果对象类
1 /// <summary> 2 /// 返回结果对象 3 /// ReturnObject Robj 4 /// 默认RCode为成功,Message为成功. 5 /// </summary> 6 /// <typeparam name="T"></typeparam> 7 public class Robj<T> 8 { 9 T result = default(T); 10 RCode code = RCode.Success; 11 string message = "操作成功"; 12 13 /// <summary> 14 /// 结果 15 /// </summary> 16 public T Result 17 { 18 get { return result; } 19 set { result = value; } 20 } 21 /// <summary> 22 /// 执行结果 23 /// </summary> 24 public RCode Code 25 { 26 get { return code; } 27 set { code = value; } 28 } 29 /// <summary> 30 /// 提示消息 31 /// </summary> 32 public string Message 33 { get { return message; } set { message = value; } } 34 35 /// <summary> 36 /// 成功 37 /// </summary> 38 /// <param name="result">返回结果</param> 39 /// <param name="msg">提示消息</param> 40 public void Success(T result,string msg = "操作成功") 41 { 42 this.code = RCode.Success; 43 this.result = result; 44 this.Message = msg; 45 } 46 47 /// <summary> 48 /// 异常 49 /// </summary> 50 /// <param name="msg">提示消息</param> 51 /// <param name="code"></param> 52 public void Error(string msg,RCode code = RCode.Exception) 53 { 54 this.code = code; 55 this.Message = msg; 56 } 57 }
2.添加返回结果处理Filter
说一下NoPackageResultAttribute特性
/// <summary> /// 标识不对返回的结果进行封装处理 /// </summary> public class NoPackageResultAttribute : Attribute { }
之前 .net Framework WebApi时,需要添加一个NoPackageResultAttribute,以处理接口不需要进行统一封装时使用.比如下载文件接口.
现在 .net Core 中已经不需要了.
下面开始添加对返回结果进行处理的Filter,Filter继承自ActionFilterAttribute,重写OnActionExecuted方法.
1 /// <summary> 2 /// ApiResult封装 3 /// </summary> 4 public class ApiResultFilter : ActionFilterAttribute 5 { 6 /// <summary> 7 /// Action执行完成,返回结果处理 8 /// </summary> 9 /// <param name="actionExecutedContext"></param> 10 public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) 11 { 12 if (actionExecutedContext.Exception == null) 13 { //执行成功 取得由 API 返回的资料 14 ObjectResult result = actionExecutedContext.Result as ObjectResult; 15 if (result != null) 16 { // 重新封装回传格式 17 Robj<object> robj = new Robj<object>(); 18 robj.Success(result.Value); 19 ObjectResult objectResult = new ObjectResult(robj); 20 actionExecutedContext.Result = objectResult; 21 } 22 } 23 base.OnActionExecuted(actionExecutedContext); 24 } 25 }
重点说明下:
(1)此处只处理Exception为Null即非异常情况.异常结果处理在另一个ExceptionHandlingMiddleware中做统一处理.
(2)只处理actionExecutedContext.Result为ObjectResult且不为Null的情况.
这样就不会对返回的其它ActionResult进行处理.比如FileResult,ContentResult,JsonResult等.
如果不需要封装的时候,只要接口返回你想要的IActionResult即可.
所以上面第一步的NoPackageResultAttribute特性在.net Core中可以不使用了.
3.完整代码如下
1 /// <summary> 2 /// ApiResult封装 3 /// </summary> 4 public class ApiResultFilter : ActionFilterAttribute 5 { 6 /// <summary> 7 /// Action执行完成,返回结果处理 8 /// </summary> 9 /// <param name="actionExecutedContext"></param> 10 public override void OnActionExecuted(ActionExecutedContext actionExecutedContext) 11 { 12 if (actionExecutedContext.Exception == null) 13 { //执行成功 取得由 API 返回的资料 14 ObjectResult result = actionExecutedContext.Result as ObjectResult; 15 if (result != null) 16 { // 重新封装回传格式 17 Robj<object> robj = new Robj<object>(); 18 robj.Success(result.Value); 19 ObjectResult objectResult = new ObjectResult(robj); 20 actionExecutedContext.Result = objectResult; 21 } 22 } 23 base.OnActionExecuted(actionExecutedContext); 24 } 25 } 26 27 /// <summary> 28 /// 返回结果对象 29 /// ReturnObject Robj 30 /// 默认RCode为成功,Message为成功. 31 /// </summary> 32 /// <typeparam name="T"></typeparam> 33 public class Robj<T> 34 { 35 T result = default(T); 36 RCode code = RCode.Success; 37 string message = "操作成功"; 38 39 /// <summary> 40 /// 结果 41 /// </summary> 42 public T Result 43 { 44 get { return result; } 45 set { result = value; } 46 } 47 /// <summary> 48 /// 执行结果 49 /// </summary> 50 public RCode Code 51 { 52 get { return code; } 53 set { code = value; } 54 } 55 /// <summary> 56 /// 提示消息 57 /// </summary> 58 public string Message 59 { get { return message; } set { message = value; } } 60 61 /// <summary> 62 /// 成功 63 /// </summary> 64 /// <param name="result">返回结果</param> 65 /// <param name="msg">提示消息</param> 66 public void Success(T result,string msg = "操作成功") 67 { 68 this.code = RCode.Success; 69 this.result = result; 70 this.Message = msg; 71 } 72 73 /// <summary> 74 /// 异常 75 /// </summary> 76 /// <param name="msg">提示消息</param> 77 /// <param name="code"></param> 78 public void Error(string msg,RCode code = RCode.Exception) 79 { 80 this.code = code; 81 this.Message = msg; 82 } 83 } 84 85 /// <summary> 86 /// 返回Code 87 /// </summary> 88 public enum RCode 89 { 90 /// <summary> 91 /// 成功 92 /// </summary> 93 [JsonProperty("1000")] 94 Success = 1000, 95 96 /// <summary> 97 /// 登录超时,需重新登录 98 /// </summary> 99 [JsonProperty("2000")] 100 NeedLogin = 2000, 101 102 /// <summary> 103 /// 程序异常 104 /// </summary> 105 [JsonProperty("3000")] 106 Exception = 3000, 107 108 /// <summary> 109 /// 系统错误 110 /// </summary> 111 [JsonProperty("4000")] 112 SysError = 4000 113 }
4.使用Filter
在StartUp ConfigureServices方法中引入Filter
services.AddMvc(options => { //加入返回结果处理 options.Filters.Add<ApiResultFilter>(); })
5.返回结果
查看返回结果如下:
{"result":{"id":"9e8e9a12-1a9b-4856-b15f-cd8debc3fb44","userName":"test","nickName":"测试","roleType":2,"userStatus":1,"addUser":"909f2444-f625-4469-8bfb-353e999944ad","addDate":"2019-05-14 00:00:00","lastLoginToken":"e68f1765-7a7e-439b-aa55-c2491516d886","lastLoginTime":"2019-07-11 12:12:44","lastLoginIp":"127.0.0.1"},"code":1000,"message":"操作成功"}