当前位置: 首页 > news >正文

.NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式

之前写过使用自定义返回类的方式来统一接口数据返回格式,.Net Core webapi RestFul 统一接口数据返回格式-CSDN博客

但是这存在一个问题,不是所有接口会按照定义的数据格式返回,除非每个接口都返回我们自定义的类,这种实现起来不太现实。

类似这样,定义一个接口:

返回的只是只有user的json对象:

这显然不是我们想要的结果,我们想要的结果是这样:

{"statusCode": 200,"successful": true,"message": null,"data": {"userId": "001","userName": "小王","password": "123"}
}

我们需要不管接口定义的返回类型是什么,最后的结果都是统一的数据格式,需要实现这个功能就需要自定义一个过滤器来实现。

具体实现代码如下:

自定义一个过滤器类 ResponseWrapperFilter.cs

public class ResponseWrapperFilter : IAsyncResultFilter{public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next){if (context.Result is ObjectResult objectResult){if (objectResult.Value is IApiResponse apiResponse){objectResult.StatusCode = apiResponse.StatusCode;context.HttpContext.Response.StatusCode = apiResponse.StatusCode;}else{var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;var wrapperResp = new ApiResponse<object>{StatusCode = statusCode,Successful = statusCode is >= 200 and < 400,Data = objectResult.Value,};objectResult.Value = wrapperResp;objectResult.DeclaredType = wrapperResp.GetType();}}await next();}}

在代码中进行判断,当响应的类型是 ObjectResult 时,把这个响应结果拿出来,再判断是不是 IApiResponse 类型。

前面我们介绍过,所有 ApiResponse 都实现了 IApiResponse 这个接口,所以可以判断是不是 IApiResponse 类型来确定这个返回结果是否包装过。

没包装的话就给包装一下,就这么简单。

附上 ApiResponse.cs  IApiResponse.cs 代码

    public interface IApiResponse{public int StatusCode { get; set; }public bool Successful { get; set; }public string? Message { get; set; }}public interface IApiResponse<T> : IApiResponse{public T? Data { get; set; }}public interface IApiErrorResponse{public Dictionary<string, object> ErrorData { get; set; }}public class ApiResponse<T> : IApiResponse<T>{public ApiResponse(){}public ApiResponse(T? data){Data = data;}public int StatusCode { get; set; } = 200;public bool Successful { get; set; } = true;public string? Message { get; set; }public T? Data { get; set; }/// <summary>/// 实现将 <see cref="ApiResponse"/> 隐式转换为 <see cref="ApiResponse{T}"/>/// </summary>/// <param name="apiResponse"><see cref="ApiResponse"/></param>public static implicit operator ApiResponse<T>(ApiResponse apiResponse){return new ApiResponse<T>{StatusCode = apiResponse.StatusCode,Successful = apiResponse.Successful,Message = apiResponse.Message};}}public class ApiResponse : IApiResponse, IApiErrorResponse{public int StatusCode { get; set; } = 200;public bool Successful { get; set; } = true;public string? Message { get; set; }public object? Data { get; set; }/// <summary>/// 可序列化的错误/// <para>用于保存模型验证失败的错误信息</para>/// </summary>public Dictionary<string, object>? ErrorData { get; set; }public ApiResponse(){}public ApiResponse(object data){Data = data;}public static ApiResponse NoContent(string message = "NoContent"){return new ApiResponse{StatusCode = StatusCodes.Status204NoContent,Successful = true,Message = message};}public static ApiResponse Ok(string message = "Ok"){return new ApiResponse{StatusCode = StatusCodes.Status200OK,Successful = true,Message = message};}public static ApiResponse Ok(object data, string message = "Ok"){return new ApiResponse{StatusCode = StatusCodes.Status200OK,Successful = true,Message = message,Data = data};}public static ApiResponse Unauthorized(string message = "Unauthorized"){return new ApiResponse{StatusCode = StatusCodes.Status401Unauthorized,Successful = false,Message = message};}public static ApiResponse NotFound(string message = "NotFound"){return new ApiResponse{StatusCode = StatusCodes.Status404NotFound,Successful = false,Message = message};}public static ApiResponse BadRequest(string message = "BadRequest"){return new ApiResponse{StatusCode = StatusCodes.Status400BadRequest,Successful = false,Message = message};}public static ApiResponse BadRequest(ModelStateDictionary modelState, string message = "ModelState is not valid."){return new ApiResponse{StatusCode = StatusCodes.Status400BadRequest,Successful = false,Message = message,ErrorData = new SerializableError(modelState)};}public static ApiResponse Error(string message = "Error", Exception? exception = null){object? data = null;if (exception != null){data = new{exception.Message,exception.Data};}return new ApiResponse{StatusCode = StatusCodes.Status500InternalServerError,Successful = false,Message = message,Data = data};}}

之后在 Program.cs 里注册一下这个过滤器

services.AddControllers(options =>
{options.Filters.Add<ResponseWrapperFilter>();
});

再次调用GetUser接口,可以看到已经包装成统一的数据格式返回了:

而对于之前已经定义返回类型是ApiResponse的接口也不会重复包装:

相关文章:

  • 无约束优化问题求解(3):共轭梯度法
  • 2023亚马逊云科技re:Invent用Amazon Q打造你的知识库
  • 力扣单调栈算法专题训练
  • ArcGIS基础:便捷查看外业照片及识别举证照片方位角
  • 案例125:基于微信小程序的个人健康数据管理系统的设计与实现
  • StringBuilder和StringBuffer区别是什么?
  • 2.3_2 进程互斥的软件实现方法
  • java类和对象的思想概述
  • .net core webapi 大文件上传到wwwroot文件夹
  • 微服务之配置中心与服务跟踪
  • 【Grafana】Grafana匿名访问以及与LDAP连接
  • Git常用命令分享
  • 论文笔记 | ICLR 2023 WikiWhy:回答和解释因果问题
  • Sentinel 流量治理组件教程
  • 用C#也能做机器学习?
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • JAVA之继承和多态
  • Mysql5.6主从复制
  • React16时代,该用什么姿势写 React ?
  • VUE es6技巧写法(持续更新中~~~)
  • Vue 重置组件到初始状态
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 关于extract.autodesk.io的一些说明
  • 聊聊hikari连接池的leakDetectionThreshold
  • 什么软件可以剪辑音乐?
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 因为阿里,他们成了“杭漂”
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • # 达梦数据库知识点
  • #FPGA(基础知识)
  • #NOIP 2014# day.1 T3 飞扬的小鸟 bird
  • #图像处理
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (Redis使用系列) Springboot 整合Redisson 实现分布式锁 七
  • (ZT)出版业改革:该死的死,该生的生
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (十)T检验-第一部分
  • (四)Linux Shell编程——输入输出重定向
  • (原)本想说脏话,奈何已放下
  • (转) RFS+AutoItLibrary测试web对话框
  • (转)linux 命令大全
  • (转)linux下的时间函数使用
  • (转)关于多人操作数据的处理策略
  • (转)平衡树
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • (总结)Linux下的暴力密码在线破解工具Hydra详解
  • *Django中的Ajax 纯js的书写样式1
  • 、写入Shellcode到注册表上线
  • .NET Core 项目指定SDK版本
  • .net core使用ef 6
  • .NET CORE使用Redis分布式锁续命(续期)问题
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)