中间件分类

ASP.NET Core 中间件的配置方法可以分为以上三种,对应的Helper方法分别是:Run(), Use(), Map()。

  • Run(),使用Run调用中间件的时候,会直接返回一个响应,所以后续的中间件将不会被执行了。
  • Use(),它会对请求做一些工作或处理,例如添加一些请求的上下文数据,有时候甚至什么也不做,直接把请求交给下一个中间件。
  • Map(),它会把请求重新路由到其它的中间件路径上去。

实际中呢,Use()这个helper方法用的最多。

Run():

这是一个使用Run方法调用的中间件,Run方法会终止整个中间件管道,它应该返回某种类型的响应。

Use():

Use看起来和Run差不多,但是多了一个next参数。next可以用来调用请求管道中的下一个中间件。而当前的中间件也可以自己返回响应,这就忽略掉了next调用。

在next调用之前,我们可以写一些请求进来的逻辑,而在next调用之后,就相当于返回响应了,这时候也可以写一些逻辑。

在本例中,我们下面还使用了Run方法注册了另一个中间件。因为中间件会按照它们注册的顺序进行调用,所以在第一个Use方法里执行next.Invoke()的时候,就会执行下面Run所调用的中间件。

Map():

Map方法可以把请求路由到其它的中间件上面。

在这里,如果请求的路径以/jump结尾,那么它所对应的handler方法,也就是HereIAm方法就会被调用,并返回一个响应。

而如果请求的路径不是以/jump结尾,那么HereIAm方法和里面的中间件就不会被调用。

中间件Class

上面的例子,我都是使用的inline写法的中间件。

而实际上,中间件通常是自成一个类。中间件的类需要类似这样:

自定义的中间件类需要由这几部分组成:

  • 接受一个RequestDelegate类型的参数next的构造函数。
  • 按约定,还需要定义一个叫做Invoke的方法。该方法里会包含主要的业务逻辑,并且它会被请求管道所执行。Invoke方法可以忽略里面的_next调用,并返回一个响应;也可以调用_next.Invoke()把请求发送到管道的下一站。

中间件流程图

Endpoint Routing 路由系统

ASP.NET Core 3.x 使用了一套叫做 Endpoint Routing 的路由系统。这套路由系统在ASP.NET Core 2.2的时候就已经露面了。

这套Endpoint Routing路由系统提供了更强大的功能和灵活性,以便能更好的处理请求。

早期ASP.NET Core的路由系统

我们先回顾一下早期版本的ASP.NET Core的路由系统:

在早期的ASP.NET Core框架里,HTTP请求进入中间件管道,在管道的结尾处,有一个Router中间件,也就是路由中间件。这个路由中间件会把HTTP请求和路由数据发送给MVC的一个组件,它叫做MVC Router Handler。

这个MVC 路由 Handler就会使用这些路由数据来决定哪个Controller的Action方法应该来负责处理这个请求。

然后 Router中间件就会执行被选中的Action方法,并生成响应,而这个响应就会顺着中间件的管道原路返回。

问题出在哪?

为什么早期的这套路由系统被抛弃了?它有什么问题?

第一个问题就是,在被MVC处理之前,其它的中间件不知道最后哪个Action方法会被选中来处理这个请求。这对像Authorization(授权),Cors这样的中间件会造成很大的困扰,因为他们不能提前知道该请求会被送往哪里。

第二个问题就是,这套流程会把MVC和路由的职责紧密的耦合在一起,而实际MVC的本职工作应该仅仅就是生成响应。

Endpoint Routing 路由系统前来营救

Endpoint routing 路由系统,它把MVC的路由功能抽象剥离出来,并放置到中间件管道里,从而解决了早期ASP.NET Core路由系统的那两个问题。

而在Endpoint Routing 路由系统里,其实一共有两个中间件,它们的名称有点容易混淆,但是你只要记住他们的职责即可:

  1. Endpoint Routing 中间件。它决定了在程序中注册的哪个Endpoint应该用来处理请求。
  2. Endpoint 中间件。它是用来执行选中的Endpoint,从而让其生成响应的。

所以,Endpoint Routing的流程图大致如下:

在这里,Endpoint Routing 中间件会分析进来的请求,并把它和在程序中注册的Endpoints进行比较。它会使用这些 Endpoints 上面的元数据来决定哪个是处理该请求的最佳人选。然后,这个选中的Endpoint 就会被赋给请求的对象,而其它后续的中间件就可以根据这个选中的Endpoint,来做一些自己的决策。在所有的中间件都执行完之后,这个被选中的Endpoint最终将被 Endpoint中间件所执行,而与之关联的Action方法就会被执行。

Endpoint是什么?

Endpoint是这样的一些类,这些类包含一个请求的委托(Request Delegate)和其它的一些元数据,使用这些东西,Endpoint类可以生成一个响应。

而在MVC的上下文中,这个请求委托就是一个包装类,它包装了一个方法,这个方法可以实例化一个Controller并执行选中的Action方法。

Endpoint还包含元数据,这些元数据用来决定他们的请求委托是否应该用于当前的请求,还是另有其它用途。

说起来可能有点迷糊,一会我们看看源码。

Startup.cs

之前我们见过,ASP.NET Core里面的Startup.cs里面有两个方法,分别是ConfigureServices()和Configure(),它们的职责就是注册应用的一些服务和构建中间件请求管道。

而Startup.cs同时也是应用的路由以及Endpoint作为其它步骤的一分部进行注册的地方。

看图:

在ASP.NET Core应用程序启动的时候,一个叫做ControllerActionEndpointDataSource的类作为应用程序级别的服务被创建了。

这个类里面有一个叫做CreateEndpoints()的方法,它会获取所有Controller的Action方法。

然后针对每个Action方法,它会创建一个Endpoint实例。这些Endpoint实例就是包装了Controller和Action方法的执行的请求委托(Request Delegate)。

ControllerActionEndpointDataSource里面包存储着在应用程序里注册的路由模板。

而针对每个Endpoint,它要么与某个按约定的路由模板相关联,要么与某个Controller Action上的Attribute路由信息相关联。而这些路由在稍后就会被用来将Endpoint与进来的请求进行匹配。

从Endpoint的角度查看请求-响应流程图

App启动那部分就不说了。

第一个HTTP请求进来的时候,Endpoint Routing中间件就会把请求映射到一个Endpoint上。它会使用之App启动时创建好的EndpointDataSource,来遍历查找所有可用的Endpoint,并检查和它关联的路由以及元数据,来找到最匹配的Endpoint。

一旦某个Endpoint实例被选中,它就会被附加在请求的对象上,这样它就可以被后续的中间件所使用了。

最后在管道的尽头,当 Endpoint中间件运行的时候,它就会执行Endpoint所关联的请求委托。这个请求委托就会触发和实例化选中的Controller和Action方法,并产生响应。最后响应再从中间件管道原路返回。

ASP.NET Core 3.x 中间件流程与路由体系的更多相关文章

  1. ASP.NET Core 1.1 静态文件、路由、自定义中间件、身份验证简介

    概述 之前写过一篇关于<ASP.NET Core 1.0 静态文件.路由.自定义中间件.身份验证简介>的文章,主要介绍了ASP.NET Core中StaticFile.Middleware ...

  2. ASP.NET Core错误处理中间件[4]: 响应状态码页面

    StatusCodePagesMiddleware中间件与ExceptionHandlerMiddleware中间件类似,它们都是在后续请求处理过程中"出错"的情况下利用一个错误处 ...

  3. Asp.Net Core 通过自定义中间件防止图片盗链的实例(转)

    一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或 ...

  4. 在Asp.net Core中使用中间件来管理websocket

    介绍 ASP.NET Core SignalR是一个有用的库,可以简化Web应用程序中实时通信的管理.但是,我宁愿使用WebSockets,因为我想要更灵活,并且与任何WebSocket客户端兼容. ...

  5. ASP.NET Core 中的中间件

    前言   由于是第一次写博客,如果您看到此文章,希望大家抱着找错误.批判的心态来看. sky! 何为中间件? 在 ASP.NET Framework 中应该都知道请求管道.可参考:浅谈 ASP.NET ...

  6. asp.net core 自定义异常处理中间件

    asp.net core 自定义异常处理中间件 Intro 在 asp.net core 中全局异常处理,有时候可能不能满足我们的需要,可能就需要自己自定义一个中间件处理了,最近遇到一个问题,有一些异 ...

  7. 给 asp.net core 写个中间件来记录接口耗时

    给 asp.net core 写个中间件来记录接口耗时 Intro 写接口的难免会遇到别人说接口比较慢,到底慢多少,一个接口服务器处理究竟花了多长时间,如果能有具体的数字来记录每个接口耗时多少,别人再 ...

  8. ASP.NET Core系列:中间件

    1. 概述 ASP.NET Core中的中间件是嵌入到应用管道中用于处理请求和响应的一段代码. 2. 使用 IApplicationBuilder 创建中间件管道 2.1 匿名函数 使用Run, Ma ...

  9. ASP.NET Core静态文件中间件[1]: 搭建文件服务器

    虽然ASP.NET Core是一款"动态"的Web服务端框架,但是由它接收并处理的大部分是针对静态文件的请求,最常见的是开发Web站点使用的3种静态文件(JavaScript脚本. ...

随机推荐

  1. 850. Dijkstra求最短路 II

    给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为正值. 请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1. 输入格式 第一行包含整数n和m. 接下来m行每行包 ...

  2. 用Gitolite搭建服务器上的Git

    使用git作为版本控制工具,确实非常流行且好用,常用的git代码服务器有Github还是国内的Gitcafe和OSC都是很不错,可以免费存放一些开源的项目代码,对于私人项目,则需要支付一定的费用.同时 ...

  3. 从头认识js-js客户端检测

    常用的客户端检测方式有以下三种: 1.能力检测 2.怪癖检测 3.用户代理检测 能力检测 最常用也是最为人们广泛接受的客户端检测形式是能力检测(又称特性检测).能力检测的目标不是识别特定的浏览器,而是 ...

  4. 记一次苹果APP从账号续费到发布成功的历程

    一.一波三折的续费      最近公司开发的苹果APP的SSL证书到期了,计划重新发布一下该APP,已替换即将到期的SSL证书.近几年随着钉钉.企业微信等在线办公软件超级平台的出现,各企业都会选择其中 ...

  5. 正式学习MVC 03

    1.View -> Controller的数据通信 1) 通过url查询字符串 public ActionResult Index(string user) { return Content(u ...

  6. SPA那点事

    前端猿一天不学习就没饭吃了,后端猿三天不学习仍旧有白米饭摆于桌前.IT行业的快速发展一直在推动着前端技术栈在不断地更新换代,前端的发展成了互联网时代的一个缩影.而单页面应用的发展给前端猿分了一杯羹. ...

  7. web前端 关于浏览器兼容的一些知识和问题解决

    浏览器兼容 为什么产生浏览器兼容,浏览器兼容问题什么是浏览器兼容: 所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况. 浏览器兼容产生的原因: 因为不 ...

  8. jinja2的url_for 和数据块

    1.静态文件引入:{{ url_for('static', filename='文件路径') }}   2.定义路由:{{ url_for('模块名.视图名',变量=参数) }}   3.定义数据块: ...

  9. C# 存储相同键多个值的Dictionary

    涉及到两个问题: 一.访问磁盘中文件夹.文件夹下面的文件夹 先看一下磁盘文件夹结构 C盘下面有个根文件夹SaveFile,SaveFIle下面有两个子文件夹分别为,2018.2019, 子文件下201 ...

  10. xml模块介绍

      # xml 是一门可拓展的语言 # xml 语法 是用<>包裹的起来的<>就是标签, xml可以由多个<>组成 也可以由单个<>组成, # < ...