.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的接口也不会重复包装:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/292643.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决IDEA编译/启动报错:Abnormal build process termination

报错信息 报错信息如下&#xff1a; Abnormal build process termination: "D:\Software\Java\jdk\bin\java" -Xmx3048m -Djava.awt.headlesstrue -Djava.endorsed.dirs\"\" -Djdt.compiler.useSingleThreadtrue -Dpreload.project.path………………很纳…

Valentina Studio Pro for Mac:高效数据库管理工具

作为一款强大而高效的数据库管理工具&#xff0c;Valentina Studio Pro for Mac在Mac平台上的表现无疑是令人印象深刻的。无论您是初学者还是专业数据库管理员&#xff0c;Valentina Studio Pro都能够满足您的需要&#xff0c;并提供一流的工具和功能来简化数据库管理的过程。 …

linux静态ip配置方法(vmware虚拟机)

1、背景 自己搭建了一个虚拟机&#xff0c;vmware虚拟机&#xff0c;如果使用动态ip,经常变换地址&#xff0c;登录不方便。 优点&#xff1a; 静态网络配置的好处是该服务器地址是静态ip的&#xff0c;不会随着网络更换而出现波动。 2、配置方法 2.1 进入centos系统&#…

HarmonyOS 应用事件打点开发指导

简介 传统的日志系统里汇聚了整个设备上所有程序运行的过程流水日志&#xff0c;难以识别其中的关键信息。因此&#xff0c;应用开发者需要一种数据打点机制&#xff0c;用来评估如访问数、日活、用户操作习惯以及影响用户使用的关键因素等关键信息。 HiAppEvent 是在系统层面…

C++之深拷贝和浅拷贝

目录 浅拷贝 深拷贝 赋值运算符重载的深拷贝 在学习C类和对象时我们学习了浅拷贝&#xff0c;本期我们将再次回顾浅拷贝并为大家讲述深拷贝的概念。 浅拷贝 在学习类和对象时我们学习了拷贝构造函数的概念&#xff0c;而且我们也知道&#xff0c;因为拷贝构造函数属于类的默…

用 树莓派 做成巨型的 Game Boy 你见过吗?

​几年前&#xff0c;华纳斯科奇&#xff08;Warner Skoch&#xff09;萌生了3D打印巨型Game Boy想法。他最初的计划是把它挂在墙上&#xff0c;用一个时钟作为屏幕&#xff0c;就像一件艺术品一样。后来&#xff0c;他的工匠头脑开始活跃起来&#xff0c;开始考虑通过添加 Ras…

3_js数组与函数的应用

1. 数组的应用 1.1 数组的概念 在计算机科学中&#xff0c;数组数据结构&#xff08;英语&#xff1a;array data structure&#xff09;&#xff0c;简称数组&#xff08;英语&#xff1a;Array&#xff09;&#xff0c;是由相同类型的元素&#xff08;element&#xff09;的…

MySQL undo日志精讲2-undo日志写入

通用链表结构 在写入undo日志的过程中会使用到多个链表&#xff0c;很多链表都有同样的节点结构&#xff0c;如图所示&#xff1a; 在某个表空间内&#xff0c;我们可以通过一个页的页号和在页内的偏移量来唯一定位一个节点的位置&#xff0c;这两个信息也就相当于指向这个节点…

基于Java+Swing实现大鱼吃小鱼小游戏(含用户登陆、注册功能)

基于JavaSwing实现大鱼吃小鱼小游戏 一、系统实现二、功能展示1.效果演示2.游戏界面3.游戏运行界面4.用户登陆 三、其他系统四源码下载 一、系统实现 1、创建窗口对象Ui 2、背景的绘制 3、键盘的监听事件 4、将己方鱼放上去 5、让小鱼移动 6、其他的鱼并引导&#xff08;先创建…

用户管理第2节课--idea 2023.2 后端--实现基本数据库操作(操作user表) -- 自动生成

一、插件 Settings... 1.1 File -- Settings 1.2 Settings -- Plugins 1.2.1 搜索框&#xff0c;也可以直接搜索 1.3 Plugins -- 【输入 & 搜索】mybatis 1.3.1 插件不同功能介绍 1.3.2 翻译如下 1.4 选中 Update&#xff0c;更新下 1.4.1 更新中 1.4.2 Restart IDE 1…

基于SpringBoot的考研专业课程管理系统 JAVA简易版

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 考研高校模块2.3 高校教师管理模块2.4 考研专业模块2.5 考研政策模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 考研高校表3.2.2 高校教师表3.2.3 考研专业表3.2.4 考研政策表 四、系统展示五、核…

GPTs | Actions应用案例

上篇文章说道&#xff0c;如何使用创建的GPTs通过API接口去获取外部的一些信息&#xff0c;然后把获取的外部信息返回给ChatGPT让它加工出来&#xff0c;回答你的问题&#xff0c;今天我们就来做一个通俗易懂的小案例&#xff0c;让大家来初步了解一下它的使用法&#xff01; …