ASP.NET 6 中间件 - 介绍与基础

dce1fae9dbc54493cf8a86c942ee0efa.png

这是一个关于 .NET 6 中间件的系列文章。

在这个系列中,我们将了解到什么是中间件,它能够做什么,以及我们为什么要使用它,并演示几种不同类型的中间件的实现。

之后,我们会进一步了解中间件所在的管道,以及如何创建它。

最后,我们再展示两种根据不同条件在管道中执行中间件的方法,以便更细粒度地控制应用程序的操作。

中间件基础

一般情况下,任何使用 HTTP 进行的交互都由请求(通常来自浏览器)和响应组成。浏览器或其他请求者通过提交请求,并等待请求目标(Web 服务器)返回响应。

中间件则位于请求者和目标之间,因此它可以直接修改响应的内容,还可以使用请求中的数据做出其它响应行为。

就像这张图:

65c2bc89b897639d918d0a698436d8f0.png

ASP.NET 6 实现了一个由一系列中间件组成的管道。请求沿着这个管道向下过滤,直到它到达一个中间件创建响应为止。然后,响应再逆向通过管道进行过滤,直到它到达请求者。

每个中间件组件由一个请求委托组成,这是 .NET 中的一种特定对象,它可以将执行控制传递给下一个对象。每个请求委托都可以选择是否将请求传递给管道中的下一个委托。

也就是说,根据请求委托处理的结果,中间件也有可能不会选择将执行控制权交给下一个委托。

中间件的用途

中间件的一个常见的场景,就是日志记录。中间件可以轻松地将请求(包括URL和路由)记录到日志系统中,以便以后进行分析。

中间件也是进行授权和身份验证、诊断、异常记录和处理的好地方。

简而言之,中间件可以用于那些不是特定于业务领域的逻辑,以及需要在每个请求或大多数请求中发生的操作。

Program.cs 示例

这是 Visual Studio 创建 ASP.NET 6 Web 应用程序时,默认生成的 Program.cs 文件,并且进行了简单的修改:

var builder = WebApplication.CreateBuilder(args);// 添加服务
builder.Services.AddRazorPages();var app = builder.Build();// 配置 HTTP 请求管道
if (!app.Environment.IsDevelopment())
{app.UseExceptionHandler("/Error");app.UseHsts();
}// 将各种中间件添加到应用程序管道中
app.UseHttpsRedirection();
app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.MapRazorPages();//最后运行应用
app.Run();

这个文件创建了 ASP.NET 6 Web 应用程序处理请求的管道。它还使用 .NET 6 提供的特殊方法向管道中添加了一组「默认」中间件。

例如UseStaticFiles(),它允许应用程序返回静态文件,如 .js 和. css;以及UseRouting() ,它添加了.NET Routing 来处理 URL 到服务器端点的路由。

此外,ASP.NET 6 应用程序可以使用很多默认提供的这种“内置”中间件。具体可以查看官方文档。

一个简单的自定义中间件

让我们创建一个超级简单的中间件,它只做一件事:返回 “Hello Dear Readers!” 作为响应。

在 Program.cs 中,我们使用 Run() 方法添加了一个新的中间件,如下所示:

app.Run(async context =>
{await context.Response.WriteAsync("Hello Dear Readers!");
});app.UseRouting();
app.UseAuthorization();app.MapRazorPages();app.Run();

当我们运行这个应用程序时,我们会看到这个非常简单的输出:

42c8c2ad73e8ab6254d812abfc8f0ef6.png

现在,我们已经在 ASP.NET 6 中实现了自定义的中间件,然而,还有一个问题,我们之后就会看到。

Run()、Use() 和 Map()

当我们查看 Program.cs 文件时,通常可以通过查看添加到管道的方法,来确定应用程序的哪些部分被认为是中间件。

最常见的方法是 Run()、Use() 和Map()。

Run()

Run() 方法会在管道的终点调用一个中间件。因此,该中间件将始终是一个终结点,也就是,响应返回之前执行的最后一个中间件。

例如前面示例的代码:

app.Run(async context =>{await context.Response.WriteAsync("Hello Dear Readers!");});// 下面的代码都不会被执行
app.UseRouting();
app.UseAuthorization();app.MapRazorPages();app.Run();

因为调用了 Run() ,所以在该调用之后不会执行任何写入的内容。

Use()

Use()方法在管道中放置一个中间件,并允许该中间件将控制权传递给管道中的下一项。

app.Use(async (context, next) =>
{//做一些不修改响应的操作await next.Invoke();//执行日志记录或不写入响应的操作
});

注意next参数,该参数就是前面提到的请求委托。它表示管道中的下一个中间件,不管它是什么。

通过等待next.Invoke(),我们允许请求继续传递到下一个中间件。

另外,请注意,除非管道在这里停止处理,否则在这种中间件中最好不要修改响应。修改已经生成的响应可能会导致响应损坏。

大多数时候我们都会使用Use()而不是Run()来添加中间件到管道中。

Map()

Map()方法允许我们创建具有分支的管道,我们可以使用它根据请求路径有条件地调用中间件。

app.Map("/branch1", HandleBranchOne);app.Map("/branch2", HandleBranchTwo);app.Run();static void HandleBranchOne(IApplicationBuilder app)
{app.Run(async context =>{await context.Response.WriteAsync("You're on Branch 1!");});
}static void HandleBranchTwo(IApplicationBuilder app)
{app.Run(async context =>{await context.Response.WriteAsync("You're on Branch 2!");});
}

Map()方法比较特殊,我们将在后面的文章中详细讨论。

总结

中间件是组成管道的代码模块或类。该管道处理传入的请求和传出的响应。

在 Program.cs 文件中,我们可以按照特定的顺序放置中间件,然后它将按照该顺序执行请求,并以相反的顺序执行响应。

ASP.NET 6 包含了很多内置的中间件,其中一些几乎可以在所有的 Web 应用中使用。

向应用管道中添加中间件的一种方法是使用Run()Use()Map()方法。然而,这可能不是最常见的方式,我们会在下一篇文章中再详细说明。

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

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

相关文章

数组的迭代数组里面每个对象添加属性值_JS数组和对象循环遍历的几种实现方式...

数组遍历1. 普通for循环let arr [1,2,3,4,5] for (let i 0; i < arr.length; i) {console.log(arr[i]) } // 输出结果 // 1 // 2 // 3 // 4 // 52. 优化普通for循环let arr [1,2,3,4,5] for(var j 0,len arr.length; j < len; j){console.log(arr[j]); }3. forEach循…

Blend4精选案例图解教程(三):一键拖拽

原文:Blend4精选案例图解教程&#xff08;三&#xff09;&#xff1a;一键拖拽拖拽效果&#xff0c;常规实现方法是定义MoveLeftDwon、MoveLeftUp、MouseMove事件&#xff0c;在Blend的世界里&#xff0c;实现对象的拖拽&#xff0c;可以不写一行代码&#xff0c;而且非常简单&…

redis学习之三配置文件redis.conf 的含义

摘自http://www.runoob.com/redis/redis-conf.html 安装redis之后的第一件事&#xff0c;我就开始配置密码&#xff0c;结果总是不生效&#xff0c;而我居然还没想到原因。今天突然用命令行设置了密码&#xff0c;居然可以了。然后info一下&#xff0c;看到配置文件位置才恍然大…

React Native之hardwareBackPress

1 hardwareBackPress 我们用hardwareBackPress来监听手机物理返回键 2 js那边常用写法 BackHandler.addEventListener(hardwareBackPress, this._back); 3 我们看下Android源代码分析是怎么触发到这里来的 1) ReactActivity.java里面的部分代码如下 Overridepublic void o…

python画气泡图_​用Python把图做的好看点:用Matplotlib画个好看的气泡图

我们继续来把简单的图形丢到极坐标&#xff0c;这次是气泡图和柱状图&#xff0c;临摹的对象是澎湃美数课这个图看起来很好看&#xff0c;原理其实很简单&#xff0c;把柱状图和气泡图从笛卡尔坐标系中转移到极坐标系中来就OK 我们开始本次的临摹吧 本期的主题如下&#xff1a;…

C#输入框InputBox问题

C#里面没有像VB一样的InputBox,但是像InputBox一样的控件在程序中很实用,这里有两种方法实现: 一、调用VB里的InputBox 首先添加引用Microsoft.VisualBasic,然后在命名空间中引用(using Microsoft.VisualBasic;)。 举个实例: using System; using System.Collections.Ge…

mysql为什么添加索引_当我添加新索引时,为什么MySQL中索引的基数保持不变?

如果表中只有1行,则索引的基数当然应为1.它只是计算唯一值的数量.如果您将索引视为基于存储桶的查找表(如散列),则基数是存储桶的数量.以下是它的工作原理&#xff1a;当您在一组列(a,b,c,d)上构建索引时,数据库将遍历表中的所有行,查看每行的4个列的有序四元组.假设你的表看起…

win32 注册表操作

创建键 RegCreateKeyEx int SetRecordVideoSavedDays(int newSavedDays)2 {3 HKEY hSubKey NULL;4 LONG lRet 0;5 DWORD dwType 0;6 int iRet 0;7 8 do 9 {10 if (newSavedDays < 0)11 {12 printf(&quo…

进程间通信(一)

1 消息队列 消息队列是消息的链接表 , 存放在内核中并由消息队列标识符标识。 m s g g e t用于创建一个新队列或打开一个现存的队列。 m s g s n d用于将新消息添加到队列尾端。 m s g r c v用于从队列中取消息。 调用的第一个函数通常是m s g g e t&#xff0c;其功能是打开一…

Asp.NET Core一个接口的多个实现如何基于当前HTTP请求注册

前言假设我们有三个Service类实现了同一接口&#xff0c;示例代码如下&#xff1a;public interface IService { } public class ServiceA : IService { } public class ServiceB : IService { } public class ServiceC : IService { }我们希望在运行时使用依赖注入指定其具体…

Loadrunner 接口测试方法

其实无论用那种测试方法&#xff0c;接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文&#xff0c;服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端&#xff0c;客户端接收应答报文这一个过程。一、基于通用http/html请求大家都知道LoadRun…

React Native之react-native bundle --platform android --dev false --entry-file index.js --bundle失败

1 问题 react native项目在assert目录下面生成index.android.bundle文件用下面的命令 react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/r…

pytorch forward_【Pytorch部署】TorchScript

TorchScript是什么&#xff1f;TorchScript - PyTorch master documentation​pytorch.orgTorchScript是一种从PyTorch代码创建可序列化和可优化模型的方法。任何TorchScript程序都可以从Python进程中保存&#xff0c;并加载到没有Python依赖的进程中。我们提供了一些工具来增量…

兼容ie8 rgba()用法

今天遇到了一个问题&#xff0c;要在一个页面中设置一个半透明的白色div。这个貌似不是难题&#xff0c;只需要给这个div设置如下的属性即可&#xff1a; background: rgba(255,255,255,.1); 但是要兼容到ie8。这个就有点蛋疼了。因为ie8不支持rgba()函数。下面我们总结一下rgb…

hdu水仙花

水仙花数Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 11 Accepted Submission(s) : 6 Problem Description 春天是鲜花的季节&#xff0c;水仙花就是其中最迷人的代表&#xff0c;数学上有个水仙花数&#xff…

python中的标识符能不能使用关键字_Python中的标识符不能使用关键字

Python中的标识符不能使用关键字答&#xff1a;√智慧职教: 检查客室座椅外观良好&#xff0c;确认?无破损答&#xff1a;坐垫 靠背关于投标报价时综合单价的确定&#xff0c;下列做法中正确的是()答&#xff1a;以项目特征描述为依据确定综合单价城市总体规划调查时&#xff…

C# WPF实战项目升级了

概述之前用Caliburn.Micro搭建的WPF实战项目&#xff0c;CM框架选用了 3.0.3&#xff0c;实际上CM框架目前最新版已经到4.0。173了&#xff0c;所有很有必须升级一下项目了. 本来打算把平台框架也直接升级到.NET 6 的&#xff0c;但是项目里面很多库不支持最新的平台版本&#…

Android之通过ContentResolver获取手机图片和视频的路径和生成缩略图和缩略图路径

1 问题 获取手机所有图片和视频的路径和生成图片和视频的缩略图和缩略图路径 生成缩略图我们用的系统函数 public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, Options options) {throw new RuntimeException("Stub!");} 调用如下 M…

ArcGIS Engine开发模板及C#代码

目 录 1. 模板 2. 代码 1. 模板 以下为AE开发软件自带的模板及代码,开发工具为VS 2012+ArcGIS Engine 10.2。 2. 代码 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; us…

为何解析浏览器地址参数会为null_request 包中出现 DNS 解析超时的探究

事情的起因是这样的&#xff0c;公司使用自建 dns 服务器&#xff0c;但是有一个致命缺陷&#xff0c;不支持 ipv6 格式的地址解析&#xff0c;而 node 的 DNS 解析默认是同时请求 v4 和 v6 的地址的&#xff0c;这样会导致偶尔在解析 v6 地址的时候出现超时。本文链接地址 htt…