.NET 7 中的 HttpResult 接口

.NET 7 中的 HttpResult 接口

Intro

在前面的文章中,我们提到了 .NET 7 引入了 Endpoint Filter 来支持 Endpoint 的过滤器,有了这个接口就想着把之前的统一 API response 的 filter 改造一下支持 endpoint filter,然而这个一直等到了 .NET 7 Preview 7 才得以实现,在 .NET 7 Preview 7 中引入了一些接口使得我们可以匹配 HttpResult 的类型

HttpResult Interface

.NET 6 开始引入了 Minimal API, 但是要匹配一系列 IResult 相关的 response 比如 Results.Ok, Results.NotFound 会比较困难,在 .NET 7 有了一些改进

在 .NET 7 Preview 3 中,出于方便单元测试的考虑,开放了一些 HttpResult 的类型比如:OkObjectHttpResult/NotFoundHttpResult 等,但是始终没有一个类似于 MVC 里的 ObjectResult 一样的类型,使得我们如果想要匹配 response 的类型就会很麻烦,终于在 .NET 7 Preview 7,引入了一系列的接口,我们可以通过这些接口进行模式匹配来获取这些 HttpResult 中的 Value/StatusCode 等等,新增加的接口如下:

Microsoft.AspNetCore.Http.IContentTypeHttpResult
Microsoft.AspNetCore.Http.IFileHttpResult
Microsoft.AspNetCore.Http.INestedHttpResult
Microsoft.AspNetCore.Http.IStatusCodeHttpResult
Microsoft.AspNetCore.Http.IValueHttpResult
Microsoft.AspNetCore.Http.IValueHttpResult<TValue>

可以参考 PR:https://github.com/dotnet/aspnetcore/pull/42385/files

如果我们想要匹配 response 的返回值就可以使用 IValueHttpResult 来匹配,比如:

if (result is IValueHttpResult valueHttpResult)return valueHttpResult.Value;

也可以使用 IStatusCodeHttpResult 来匹配 response status

if (result is IStatusCodeHttpResult statusCodeResult)return statusCodeResult.StatusCode;

ApiResultFilter

实现了一个简单的统一 response 的 ApiResultFilter ,在原来的基础上增加了 EndpointFilter 的支持,实现如下:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class ApiResultFilter : Attribute, IResultFilter, IExceptionFilter
#if NET7_0_OR_GREATER, IEndpointFilter
#endif{public void OnResultExecuting(ResultExecutingContext context){if (context.Result is ObjectResult { Value: not Result } objectResult){var result = new Result<object>(){Data = objectResult.Value,Status = HttpStatusCode2ResultStatus(objectResult.StatusCode)};objectResult.Value = result;}}public void OnResultExecuted(ResultExecutedContext context){}public void OnException(ExceptionContext context){var result = Result.Fail(context.Exception.ToString(), ResultStatus.ProcessFail);context.Result = new ObjectResult(result) { StatusCode = 500 };}
#if NET7_0_OR_GREATERpublic async ValueTask<object> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next){try{var result = await next(context);if (result is Result or ObjectResult { Value: Result } or IValueHttpResult { Value: Result }){return result;}if (result is ObjectResult { Value: not Result } objectResult){return new Result<object>(){Data = objectResult.Value, Status = HttpStatusCode2ResultStatus(objectResult.StatusCode)};}if (result is IValueHttpResult { Value: not Result } valueHttpResult){var status = result is IStatusCodeHttpResult statusCodeHttpResult? HttpStatusCode2ResultStatus(statusCodeHttpResult.StatusCode): HttpStatusCode2ResultStatus(200);return new Result<object>() { Data = valueHttpResult.Value, Status = status };}return new Result<object>(){Data = result, Status = HttpStatusCode2ResultStatus(context.HttpContext.Response.StatusCode)};}catch (Exception ex){return Result.Fail(ex.ToString(), ResultStatus.ProcessFail);}}
#endifprivate static ResultStatus HttpStatusCode2ResultStatus(int? statusCode){statusCode ??= 200;var status = ResultStatus.Success;if (Enum.IsDefined(typeof(ResultStatus), statusCode.Value)){status = (ResultStatus)statusCode.Value;}if (status == ResultStatus.None){status = ResultStatus.Success;}return status;}
}

下面看一个使用的示例:

var app = WebApplication.Create(args);
app.Map("/Hello", () => "Hello Minimal API!").AddEndpointFilter<ApiResultFilter>();
app.Map("/HelloV3", () => Results.Ok(new { Name = "test" })).AddEndpointFilter<ApiResultFilter>();
app.Map("/HelloV4", () => Results.Ok(Result.Success(new { Name = "test" }))).AddEndpointFilter<ApiResultFilter>();
await app.RunAsync();

访问一个直接返回一个字符串的接口:

1baa9b98ef78e601601d665591648912.png

访问返回一个 IResult 的接口

d2293cc49dd0dc5e87c7e51494cea69a.png

访问返回一个 ResultModel 的 API

d3c708ce46a24e3b20b07c4488d70685.png

使用控制器 API 示例:

[Route("api/[controller]")]
public class ValuesController: ControllerBase
{[HttpGet("[action]")]public IActionResult Test(){return Ok(new { Name = "Amazing .NET" });}
}

API response 示例:

dfdba61746aed664a99a7c17c1f83c17.png

References

  • https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-7/#new-httpresults-interfaces

  • https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-3/#improved-unit-testability-for-minimal-route-handlers

  • https://github.com/dotnet/aspnetcore/issues/41470

  • https://github.com/dotnet/aspnetcore/issues/42187

  • https://github.com/dotnet/aspnetcore/pull/42385/files

  • https://github.com/WeihanLi/WeihanLi.Web.Extensions/tree/dev/samples/WeihanLi.Web.Extensions.Samples

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

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

相关文章

5、Hive的自定义UDF函数

2019独角兽企业重金招聘Python工程师标准>>> 1、pom.xml引入依赖及打包 <dependencies><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>1.1.0</version></depende…

多线程-单生产单消费模型

2019独角兽企业重金招聘Python工程师标准>>> 创建资源对象&#xff0c;提供保存和取出方法&#xff08;使用synchronized代码块实现&#xff09; /*** Created by shaoqinghua on 2018/5/3.* 定义一个负责保存和取出的资源类*/ public class Resource {/*** 定义成员…

nj08---process、console

概念&#xff1a;所有属性都可以在程序的任何地方访问&#xff0c;即全局变量。在JavaScript中&#xff0c;通常window是全局对象&#xff0c;而Node.js的全局对象是global&#xff0c;所有全局变量都是global对象的属性&#xff0c;如&#xff1a;console、process等。一、全局…

github1s 油猴插件

github1s 是一个非常有趣的项目&#xff0c;它可以让你在 1 秒内&#xff08;俗称 1s&#xff09;通过在线版本的 VS Code 来打开 GitHub 上的代码&#xff0c;只需要在对应项目的 URL 后面加上 1s 即可。 这是一个很有创意、很赞的项目&#xff0c;只需要在对应的 GitHub 项目…

WPF-02 布局

WPF中布局控件继承Panel&#xff0c;可以实现非常复杂的布局。我们介绍一下常用的布局控件1. Grid 布局控件Grid是网格布局控件&#xff0c;在WPF开发中我们用的最多的一个布局控件&#xff0c;可以自定义行和列&#xff0c;分别设置Height和Witdh值&#xff0c;一般推荐通过比…

275mib为什么不能联网_大众迈腾(275)MIB之导航使用教程

大众可以说近几年的发展非常快&#xff0c;仅车载收音机都更换了好几代了。从最初的单纯收音机到后来的6碟CD机RCD510&#xff0c;最初国内上市的导航RNS510&#xff0c;还有后来自带蓝牙的RNS315&#xff0c;再到PQ平台187A&#xff0c;当初抄的也火的几乎每天都看到187…

微信多开工具 可以同时在电脑上打开多个微信 免费开源

本程序用C#代码编写&#xff0c;运行环境FrameWork5.0以上。 主要代码&#xff1a; using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using Sys…

Linux 第十周学习笔记(2)smtp服务的部署

SMTP服务的部署介绍&#xff1a;SMTP(Simple Mail Transfer Protocol)简单邮件传输协议是一种提供可靠且有效电子邮件传输的协议。 SMTP 是建模在 FTP 文件传输服务上的一种邮件服务&#xff0c;主要用于传输系统之间的邮件信息并提供来信有关的通知。一&#xff0e;环境的部署…

关于CTeX的几个大坑

https://blog.csdn.net/zjutczj/article/details/53463478 最近一直忙着写小论文&#xff0c;毕业设计中期答辩&#xff0c;没有更新博客&#xff0c;忙过这一阵我会把这段时间学习机器学习的一些心得分享。今天分享几个刚刚使用CTeX遇到的大坑&#xff0c;希望能挽救一些还没有…

西安电子地图下载 来自谷歌电子地图库 地图展示15、17、19级

西安电子地图下载 来自谷歌电子地图库 地图展示15、17、19级 一般来说商业用图几乎相同就是17级左右&#xff0c;提供的下载全然满足大多数人浏览使用&#xff0c;假设用于旅行外出当然级数越高越好&#xff0c;假设是驴行&#xff0c;那就更有必要下载完整的地图以作不时之需。…

0x0000050蓝屏srvsys_蓝屏代码0x00000050的原因及解决方法

经常使用电脑的朋友都知道&#xff0c; 电脑开机 出现蓝屏现象很普遍&#xff0c;相信大家都有遇到过吧?让我们经常的手足无措&#xff0c;不知道接下来应该怎么去操作!那么现在小编汇总起来告诉给大家出现蓝屏代码0x00000050怎么解决的具体内容&#xff0c;先对电脑进行局部的…

​Magicodes.Pay已支持Volo Abp

简介Magicodes.Pay希望打造一个统一支付库&#xff0c;相关库均使用.NET标准库编写&#xff0c;支持.NET Framework以及.NET Core。目前已提供Abp及Abp VNext模块的封装&#xff0c;支持开箱即用。主要功能目前已提供Abp&#xff08;含Abp VNext&#xff09;模块的封装&#xf…

js继承

js继承 一、总结 1、js继承&#xff1a;和c&#xff0c;java不一样&#xff0c;是通过对象冒充&#xff0c; 原型链&#xff0c;混合模式来实现的 2、基础打牢&#xff1a;基础打牢&#xff0c;后面就很轻松 二、js继承 继承继承的相关概念 这里的继承和我们现实生活的中儿子继…

Linux console on LCD

有时候需要将开机启动的信息输出到LCD上&#xff0c;并且在终端上进行调试。本文记录更改的方法。 参考链接 http://blog.csdn.net/chenbang110/article/details/7870072 https://e2e.ti.com/support/embedded/linux/f/354/t/324198 https://blackfin.uclinux.org/doku.php?id…

vscode 头文件包含问题_WSL+VSCode = Linux ?

官方文档​code.visualstudio.com使用VSCode新推出的Remote功能来连接WSL或服务器进行开发. 可以在Windows上享受优秀的界面体验的同时使用Linux环境进行开发(还是要感谢无数的VSCode插件贡献者).环境基础配置Visual Studio Code最新版本注意点: 安装时需要勾选环境变量添加到p…

PerfView专题 (第十篇):洞察 C# 终结队列引发的内存泄漏

一&#xff1a;背景 C# 程序内存泄漏的诱发因素有很多&#xff0c;但从顶层原理上来说&#xff0c;就是该销毁的 用户根 对象没有被销毁&#xff0c;从而导致内存中意料之外的对象无限堆积&#xff0c;导致内存暴涨&#xff0c;最终崩溃&#xff0c;这其中的一个用户根就是 终结…

【JS第34期】BOM-window对象

BOM的核心对象是window,它表示浏览器的一个实例。它即是通过javascript访问浏览器窗口的一个接口&#xff0c;也是ECMAScript规定的Global对象。 全局作用域 由于window对象同时是Global对象&#xff0c;因此所有在全局作用域中声明的变量、函数会变成window对象的属性和方法。…

proc文件(OLD)

写一个模块测试proc文件的读写&#xff1a; 1 #include linux/module.h 2 #include linux/kernel.h 3 #include linux/proc_fs.h 4 #include linux/sched.h 5 #include asm/uaccess.h 6 7 #define STRINGLEN 1024 8 9 char global_buffer[STRINGLEN]; 10 11 struct…

java学习(七)java中抽象类及 接口

抽象类的特点&#xff1a; A&#xff1a;抽象类和抽象方法必须用abstract关键字修饰。 B:抽象类中不一定有抽象方法&#xff0c;但是抽象方法的类必须定义为抽象类 c: 抽象类不能被实例化&#xff0c;因为它不是具体的。 抽象类有构造方法&#xff0c;但不能被实例化&#xff1…

手机的小窗口怎么弄_荣耀9X如何设置桌面小工具?划重点,这个要考

为了方便手机操作&#xff0c;一些小伙伴会在手机桌面上添加天气、一键锁屏、日历等窗口小工具&#xff0c;那么问题来了&#xff01;荣耀9X这款新手机是如何添加窗口小工具呢&#xff1f;官维君今天就来给大家讲解一下方法。标准姿势看这里——第一步&#xff1a;在桌面双指头…