ASP.NET Core 管道再探

几乎任何服务器端处理环境都有自己的直通组件管道,用于检查、重路由或修改传入请求和传出响应。经典 ASP.NET 围绕 HTTP 模块理念进行排列,而 ASP.NET Core 采用基于中间件组件的更现代的体系结构。最终目的是相同的 - 允许可配置的外部模块以请求(以及稍后的响应)在服务器环境中传递的方式进行干预。中间件组件的主要目的是以某种方式改变和筛选数据流(在某些特定情况下,只是使请求短路,停止任何进一步的处理)。

ASP.NET Core 管道自框架 1.0 版发布以来几乎没有变化,但即将发布的 ASP.NET Core 3.0 邀请了一些关于当前体系结构的评论,这些评论在很大程度上被忽略了。因此,在本文中,我将重新讨论 ASP.NET Core 运行时管道的整体功能,并着重介绍 HTTP 终结点的角色和可能的实现。

适用于 Web 后端的 ASP.NET Core

特别是在过去几年,构建前端和后端完全解耦的 Web 应用程序已经变得相当普遍。因此,大多数 ASP.NET Core 项目现在都是简单的没有 UI 的 Web API 项目,仅为单页面和/或移动应用程序提供 HTTP 外观,大多数情况下,这些应用通过 Angular、React、Vue 及其移动对等项构建而成。

当你意识到这一点,将出现一个问题:在不使用任何 Razor 工具的应用程序中,绑定到 MVC 应用程序模型是否仍有意义?MVC 模型并不是免费的,事实上,在某种程度上,一旦停止使用控制器来提供操作结果,它甚至可能不是最轻量级的选项。进一步追问:如果大部分 ASP.NET Core 代码编写只是为了返回 JSON 有效负载,那么操作结果概念本身是否绝对必要?

带着这些想法,让我们回顾一下 ASP.NET Core 管道和中间件组件的内部结构,以及可以在启动期间绑定到的内置运行时服务列表。

启动类

在任何 ASP.NET Core 应用程序中,一个类被指定为应用程序引导程序。大多数情况下,此类采用名称“Startup”。该类在 Web 主机配置中声明为启动类,Web 主机通过反射实例化并调用该类。该类可以有两种方法 - ConfigureServices(可选)和 Configure。在第一个方法中,你将接收当前(默认)运行时服务列表,并需要添加更多服务来为实际应用程序逻辑做准备。在 Configure 方法中,为默认服务和显式请求支持应用程序的服务进行配置。

Configure 方法接收至少一个应用程序生成器类实例。可以将此实例视为传递给代码的 ASP.NET 运行时管道的工作实例,以便根据需要进行配置。一旦 Configure 方法返回,管道工作流将配置完毕,并用于执行从连接的客户端发送的任何进一步请求。图 1 提供了 Startup 类的 Configure 方法的实现示例。

图 1 Startup 类中 Configure 方法的基本示例

Use 扩展方法是用于将中间件代码添加到其他空管道工作流的主要方法。注意,添加的中间件越多,服务器需要执行更多的工作来满足任何传入请求。最小的是管道,最快的是客户端至第一字节的时间 (TTFB)。

可以使用 lambdas 或临时中间件类向管道添加中间件代码。这完全由你来决定:lambda 更直接,但类(最好是一些扩展方法)将使整个过程更易于阅读和维护。中间件代码获取请求的 HTTP 上下文和对管道中下一个中间件的引用(如果有的话)。图 2 显示了各种中间件组件链接在一起的总体视图。

640?wx_fmt=png

图 2 ASP.NET Core 运行时管道

每个中间件组件都有两次机会介入正在进行的请求的生命周期。它可以预先处理从先前注册运行的组件链接收到的请求,然后它会被链中的下一个组件取代。当链中的最后一个组件有机会预先处理请求时,请求会被传递给终止中间件,以便进行实际处理,目的是生成具体输出。之后,组件链按相反顺序返回,如图 2 所示,每个中间件都有第二次处理的机会 - 不过,这一次将是后处理操作。在图 1 代码中,预处理代码与后处理代码的分割线为:

终止中间件

在图 2 所示的体系结构中,关键是终止中间件的角色,它是 Configure 方法底部的代码,用于终止链并处理请求。所有演示 ASP.NET Core 应用程序都有一个终止的 lambda,如下所示:

lambda 接收 HttpContext 对象,并在应用程序上下文中执行它应执行的任何操作。

实际上,有意不生成到下一个组件的中间件组件将终止链,进而导致响应被发送到请求的客户端。UseStaticFiles 中间件就是一个很好的例子,它在指定的 Web 根文件夹下提供静态资源,并终止请求。另一个示例是 UseRewriter,它可以命令客户端重定向到新 URL。在没有终止中间件的情况下,请求很难在客户端上产生一些可见输出,尽管响应仍然通过运行中间件(例如,通过添加 HTTP 标头或响应 cookie)以修改后的形式发送。

还有两个专用的中间件工具也可用于短路请求:app.Map 和 app.MapWhen。前者检查请求路径是否匹配参数并运行自己的终止中间件,如下所示:

而后者仅在验证了指定布尔条件后才运行自己的终止中间件。布尔条件来自接受 HttpContext 的函数计算。图 3 中的代码提供了一个非常精简的小型 Web API,它仅为单个终结点提供服务,并且在没有任何类似于控制器类项的情况下执行该操作。

图 3 极小型 ASP.NET Core Web API

如果 URL 匹配 /country,终止中间件将从查询字符串中读取一个参数,并安排对存储库的调用,以获得匹配国家/地区列表。然后,对列表对象以 JSON 格式直接手动序列化到输出流。通过添加一些其他映射路由,你甚至可以扩展 Web API。再简单不过了。

MVC 怎么样?

在 ASP.NET Core 中,整个 MVC 机制作为黑盒运行时服务提供。只需绑定到 ConfigureServices 方法中的服务,并在 Configure 方法中配置其路由,如下面的代码所示:

此时,如果你打算提供 HTML,欢迎填充常用的 Controllers 文件夹,甚至 Views 文件夹。注意在 ASP.NET Core 还可以使用 POCO 控制器,它是简单的 C# 类,经修饰后可以被识别为控制器,并与 HTTP 上下文断开连接。

MVC 机制是终止中间件的另一个很好的示例。一旦请求被 MVC 中间件捕获,一切都在它的控制之下,管道会突然终止。

有趣的是,MVC 机制在内部运行自己的自定义管道。它不以中间件为中心,但它仍然是一个完整的运行时管道,控制请求如何路由到控制器操作方法,并最终将生成的操作结果呈现到输出流。MVC 管道由在各个控制器方法前后运行的各种类型的操作筛选器(操作名称选择器、授权筛选器、异常处理程序、自定义操作结果管理器)组成。在 ASP.NET Core 中,内容协商也隐藏在运行时管道中。

从更深刻的角度来看,整个 ASP.NET MVC 机制看起来就像是被固定在最新的、经重新设计的、以中间件为中心的 ASP.NET Core 管道的上方。就像 ASP.NET Core 管道和 MVC 机制是不同类型的实体,只是以某种方式连接在一起。总体情况与 MVC 被固定在现已被摒弃的 Web 窗体运行时之上的方式没有太大不同。实际上,在该上下文中,如果处理请求无法与物理文件匹配(很可能是 ASPX 文件),MVC 就会通过专用的 HTTP 处理程序启动。

这有问题吗?很可能没有。也许问题还没出现!

将 SignalR 置于循环中

将 SignalR 添加到 ASP.NET Core 应用程序时,需要做的就是创建一个中心类来公开终结点。有趣的是中心类可能与控制器完全不相关。不需要 MVC 来运行 SignalR,但中心类的行为类似于外部请求的前端控制器。从中心类公开的方法可以执行任何工作 - 甚至与框架的跨应用通知性质无关的工作,如图 4 所示。

图 4 从中心类公开方法

能看到图片吗?

SignalR 中心类可以被视为一个控制器类,不需要整个 MVC 机制,非常适合无 UI(或者更确切地说,是 Razor)响应。

将 gRPC 置于循环中

在 3.0 版本中,ASP.NET Core 还提供了对 gRPC 框架的本机支持。该框架设计为与 RPC 准则一起使用,是围绕接口定义语言的一层代码,接口定义语言完全定义终结点,并且能够使用 HTTP/2 上的 Protobuf 二进制序列化触发连接方之间的通信。从 ASP.NET Core 3.0 角度来看,gRPC 还是另一个可调用外观,可以进行服务器端计算并返回值。下面介绍了如何启用 ASP.NET Core 服务器应用程序以支持 gRPC:

另请注意全局路由的使用,以使应用程序支持没有 MVC 机制的路由。可以将 UseRouting 视为定义 app.Map 中间件块的一种更结构化的方法。

前面代码的净效果是支持从客户端应用程序到映射服务的 RPC 样式调用,即 Greeter­Service 类。有趣的是,GreeterService 类在概念上等同于 POCO 控制器,只不过它不需要被识别为控制器类,如下所示:

基类(GreeterBase 是一个封装在静态类中的抽象类)包含执行请求/响应通信所需的管道。gRPC 服务类与 ASP.Net Core 基础结构完全集成,可以注入外部引用。

底线

特别是随着 ASP.NET Core 3.0 的发布,将会出现另外两种情况,在这些情况下,使用无 MVC 的控制器样式外观将会很有帮助。SignalR 有一个中心类,gRPC 有一个服务类,但关键是它们在概念上是相同的,必须在不同的场景以不同方式实现这些类。MVC 机制已或多或少被移植到 ASP.NET Core,因为它最初是为经典 ASP.NET 设计的,并围绕控制器和操作结果维护自己的内部管道。与此同时,随着 ASP.NET Core 越来越广泛地被用作普通后端服务提供程序(不支持视图),对 HTTP 终结点可能统一的 RPC 样式外观的需求也在增长。

原文地址:https://msdn.microsoft.com/zh-cn/magazine/mt833464


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

640?wx_fmt=jpeg

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

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

相关文章

GRPC与.net core

QQ讨论群:953553560正文系列章节GRPC与.net coreGRPC截止时间与元数据GRPC与netcore IdentityGRPC与netcore IdentityServer4概述GRPC的数据交互模式有:1.单项RPC,最简单的数据交换方式,客户端发出单个请求,收到单个响…

程序员修神之路--做好分库分表其实很难之一

点击上方“蓝字”带你去看小星星菜哥,领导让我开发新系统了这么说领导对你还是挺信任的呀~必须的,为了设计好这个新系统,数据库设计我花了好多心思呢做一个系统我觉得不应该从数据库入手,应该从设计业务模型开始,先不说…

Office 365开发者的前端必备课程

这篇文章其实不仅仅是写给Office 365开发者的,但对于广大的Office 365开发者来说确实相当重要的。这里提到的Office 365开发者,包括了Office Add-ins,SharePoint Add-ins,Microsoft Graph,Microsoft Teams的开发者。我…

【CF1338C】Perfect Triples【位运算】【构造】

传送门 题意:有一序列SSS由下列方式生成: 找到字典序最小的正整数(a,b,c)(a,b,c)(a,b,c),满足a,b,ca,b,ca,b,c不在SSS中且a⊕b⊕c0a\oplus b\oplus c0a⊕b⊕c0,其中⊕\oplus⊕为异或将a,b,ca,b,ca,b,c加入SSS重复第一步 TTT组数据&#xff…

.NET开发框架(五)-IIS上部署ASP.NET Core项目教程

在之前教程中,我们分享了框架的功能与视频演示介绍(文尾底部提供往期教程快捷链接)系列教程:从初学者到架构师的一步步蜕变本篇经验将和大家介绍如何在IIS上部署ASP.NET Core项目,希望对初学.NET CORE的童靴入门有所帮助!1、打开V…

P4146 序列终结者 平衡树 + lazy维护

传送门 文章目录题意:思路:题意: 思路: 平衡树裸题,直接维护俩lazylazylazy就行了。 需要注意的是,只有儿子节点存在的时候才能更新,不然更新到000号节点之后,给000号点加上了奇怪的…

.NET开发框架(四)-服务器IIS实践教程

前三篇教程中,我们分享了框架的功能与视频演示介绍(文尾底部提供往期教程快捷链接),今天开始我们进入实践教程,从0开始教学,让你从新手到架构师之兑变,目前已经重置了一台服务器,从安装与配置各组件开始学习…

.NET Core IdentityServer4实战 第六章-Consent授权页

在identityServer4中登陆页面只要是成功了,就会注册一个Cookie在服务器资源上,像现在大部分的网站第三方授权,都是经过一个页面,然后选需要的功能,IdentityServer4也给我们提供了,只要你登陆成功,就会跳转到…

GitHub的CI实践(xUnit / OpenCover /Appveyor / Coveralls.net)

最近利用业余时间实现.ner core 版本的 casbin ,即 Casbin.NET。之前的CI都使用的是公司搭建的jenkins和gitlab-runner,对开源社区的工具链并不是很熟悉,在casbin的原作者(hsluoyz )的“要求”下,只能被迫在项目的README.md加入下…

P4847 银河英雄传说V2 非旋treap

传送门 文章目录题意:思路:题意: 思路: 让我们分析一下题目需要实现什么操作: (1)(1)(1)将某个序列放到某个的后面,也就是合并两个序列。 (2)(2)(2)将一个序列从某处断开。 (3)(3)(3)查询某个序列的一段和…

小白开学Asp.Net Core 《五》

小白开学Asp.Net Core《五》—— 使用.Net Core MVC Filter一、简介今天在项目(https://github.com/AjuPrince/Aju.Carefree)做登陆权限时,用到了Filter,现将Filer的使用做以下记录。二、Filter 简介Filter俗称过滤器,…

P5217 贫穷 平衡树

传送门 文章目录题意:思路:题意: 思路: 本来是不想写数据结构了,因为明天打蓝桥了,想放松一下,但是看到这个题感觉写起来挺简单的,就试了试,结果… 首先看一下他的操作…

高性能微服务网关.NETCore客户端Kong.Net开源发布

前言项目地址:https://github.com/lianggx/Kong.Net你的支持使我们更加强大,请单击 star 让更多的 .NETCore 认识它。拥抱开源的脚步,我们从来都是一直在路上;.NETCore作为后起之秀,带给我们太多的惊喜和感动&#xff…

使用Jenkins部署.Net Core遇到的几个坑

一、相关环境和版本搞过CI/CD的同学一定吃过不少苦头,或者说遇到不少坑,但是对自动化的执着住挡不了前进的步伐,如果你缺少了运维这一块知识,那么你的流水线总是不那么完美,本文记录的是自己躺过的坑,希望对…

Deltix Round, Spring 2021 E. Crypto Lights 组合数学 + 推公式

传送门 文章目录题意:思路:题意: 给你nnn个灯,每次可以打开一个灯,当连续的kkk个灯有至少两个灯开着的时候停止,问最终期望能打开多少灯。 思路: 由于不想打latexlatexlatex,所以…

.NET Core 仿魔兽世界密保卡实现

《魔兽世界》的老玩家都知道,密保卡曾经被用于登录验证,以保证账号安全。今天我用.NET Core模拟了一把密保卡(也叫矩阵卡)的实现,分享给大家。密保卡的原理这是一张典型的魔兽世界密保卡。序列号用于绑定游戏账号&…

浅谈C#泛型

一.为什么要提出泛型的概念我们在声明对象或者方法中,对象中成员变量的定义或者函数参数都传递都要指定具体的对象类型,但是有的时候参数的类型是变化的,但是实现的功能却又差不多,这个时候我们就想,是否存在一种东西可…

【半小时大话.net依赖注入】(一)理论基础+实战控制台程序实现AutoFac注入

第一章|理论基础实战控制台程序实现AutoFac注入第二章|AutoFac的常见使用套路第三章|实战Asp.Net Framework Web程序实现AutoFac注入第四章|实战Asp.Net Core自带DI实现依赖注入第五章|实战Asp.Net Core引入AutoFac的两种方式简介该系列共5篇文章,旨在以实战模式&am…

P4198 楼房重建 线段树 + 区间合并

传送门 文章目录题意:思路:题意: 题面有点问题,按照人类正常的理解来就好啦。 思路: 可以想到维护每个位置的一个斜率,模拟的话就是从第一个位置开始向后选,当某个位置斜率大于当前位置的时…

基于 Docker Compose 实践 .NET Core 的现代化架构 2:在容器中集成 Skywalking APM

本章节代码已经上传至 https://github.com/siegrainwong/.NET-Core-with-Docker/tree/master/Part2系列大纲还是先介绍一下目录,这次我们讲第二篇:用 docker-compose 启动 WebApi 和 SQL Server在容器中集成 Skywalking APM通过 nginx-proxy 对 ES、Skyw…