原文:ASP.NET Core 2 学习笔记(三)中间件

之前ASP.NET中使用的HTTP Modules及HTTP Handlers,在ASP.NET Core中已不复存在,取而代之的是Middleware。Middleware除了简化了HTTP Modules/Handlers的使用方式,还带入了Pipeline的概念。
本篇将介绍ASP.NET Core的Middleware概念及用法。

Middleware 概念

ASP.NET Core在Middleware的官方说明中,使用了Pipeline这个名词,意指Middleware像水管一样可以串联在一起,所有的Request及Response都会层层经过这些水管。
用图例可以很容易理解,如下图:

App.Use

Middleware的注册方式是在Startup.csConfigureIApplicationBuilder使用Use方法注册。
大部分扩展的Middleware也都是以Use开头的方法注册,例如:

  • UseMvc():MVC的Middleware
  • UseRewriter():URL rewriting的Middleware

一个简单的Middleware 范例。如下:

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;namespace MyWebsite
{public class Startup{// This method gets called by the runtime. Use this method to add services to the container.// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940public void ConfigureServices(IServiceCollection services){}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use(async (context, next) =>{await context.Response.WriteAsync("First Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("First Middleware out. \r\n");});app.Use(async (context, next) =>{await context.Response.WriteAsync("Second Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("Second Middleware out. \r\n");});app.Use(async (context, next) =>{await context.Response.WriteAsync("Third Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("Third Middleware out. \r\n");});app.Run(async (context) =>{await context.Response.WriteAsync("Hello World! \r\n");});}}
}

用浏览器打开网站任意连结,输出结果: 

First Middleware in.
Second Middleware in.
Third Middleware in.
Hello World!
Third Middleware out.
Second Middleware out.
First Middleware out.

在Pipeline的概念中,注册顺序是很重要的事情。请求经过的顺序一定是先进后出。

Request 流程如下图:

Middleware 也可以作为拦截使用,如下:

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;namespace MyWebsite
{public class Startup{// This method gets called by the runtime. Use this method to add services to the container.// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940public void ConfigureServices(IServiceCollection services){}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use(async (context, next) =>{await context.Response.WriteAsync("First Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("First Middleware out. \r\n");});app.Use(async (context, next) =>{await context.Response.WriteAsync("Second Middleware in. \r\n");// 水管阻塞,封包不往后送var condition = false;if (condition){await next.Invoke();}await context.Response.WriteAsync("Second Middleware out. \r\n");});app.Use(async (context, next) =>{await context.Response.WriteAsync("Third Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("Third Middleware out. \r\n");});app.Run(async (context) =>{await context.Response.WriteAsync("Hello World! \r\n");});}}
}

输出结果:

First Middleware in.
Second Middleware in.
Second Middleware out.
First Middleware out.

在Second Middleware 中,因为没有达成条件,所以封包也就不在往后面的水管传送。流程如图:

App.Run

Run是Middleware的最后一个行为,以上面图例来说,就是最末端的Action。
它不像Use能串联其他Middleware,但Run还是能完整的使用Request及Response。

App.Map

Map是能用来处理一些简单路由的Middleware,可依照不同的URL指向不同的Run及注册不同的Use
新增一个路由如下:

Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;namespace MyWebsite
{public class Startup{// This method gets called by the runtime. Use this method to add services to the container.// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940public void ConfigureServices(IServiceCollection services){}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.Use(async (context, next) =>{await context.Response.WriteAsync("First Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("First Middleware out. \r\n");});// app.Use(async (context, next) =>// {//     await context.Response.WriteAsync("Second Middleware in. \r\n");//     // 水管阻塞,封包不往后送//     var condition = false;//     if (condition)//     {//         await next.Invoke();//     }//     await context.Response.WriteAsync("Second Middleware out. \r\n");// });app.Map("/second", mapApp =>{mapApp.Use(async (context, next) =>{await context.Response.WriteAsync("Second Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("Second Middleware out. \r\n");});mapApp.Run(async context =>{await context.Response.WriteAsync("Second. \r\n");});});app.Use(async (context, next) =>{await context.Response.WriteAsync("Third Middleware in. \r\n");await next.Invoke();await context.Response.WriteAsync("Third Middleware out. \r\n");});app.Run(async (context) =>{await context.Response.WriteAsync("Hello World! \r\n");});}}
}

开启网站任意连结,会显示:

First Middleware in.
Third Middleware in.
Hello World!
Third Middleware out.
First Middleware out.

开启网站http://localhost:5000/second,则会显示:

First Middleware in.
Second Middleware in.
Second.
Second Middleware out.
First Middleware out.

创建Middleware 类

如果Middleware全部都写在Startup.cs,代码将很难维护,所以应该把自定义的Middleware逻辑独立出来。
建立Middleware类不需要额外继承其它类或接口,一般的类即可,例子如下:

FirstMiddleware.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;namespace MyWebsite
{public class FirstMiddleware{private readonly RequestDelegate _next;public FirstMiddleware(RequestDelegate next){_next = next;}public async Task Invoke(HttpContext context){await context.Response.WriteAsync($"{nameof(FirstMiddleware)} in. \r\n");await _next(context);await context.Response.WriteAsync($"{nameof(FirstMiddleware)} out. \r\n");}}
}

全局注册

Startup.Configure注册Middleware就可以套用到所有的Request。如下:

Startup.cs

// ...
public class Startup
{// ...public void Configure(IApplicationBuilder app){app.UseMiddleware<FirstMiddleware>();// ...}
}

局部注册

Middleware 也可以只套用在特定的Controller 或Action。注册方式如下:

Controllers\HomeController.cs

// ..
[MiddlewareFilter(typeof(FirstMiddleware))]
public class HomeController : Controller
{// ...[MiddlewareFilter(typeof(SecondMiddleware))]public IActionResult Index(){// ...}
}

Extensions

大部分扩展的Middleware都会用一个静态方法包装,如:UseMvc()UseRewriter()等。
自定义的Middleware当然也可以透过静态方法包,范例如下:

Extensions\CustomMiddlewareExtensions.cs

using Microsoft.AspNetCore.Builder;namespace MyWebsite
{public static class CustomMiddlewareExtensions{public static IApplicationBuilder UseFirstMiddleware(this IApplicationBuilder builder){return builder.UseMiddleware<FirstMiddleware>();}}
}

注册Extension Middleware 的方式如下:

Startup.cs

// ...
public class Startup
{// ...public void Configure(IApplicationBuilder app){app.UseFirstMiddleware();// ...}
}

参考

ASP.NET Core Middleware Fundamentals 
Creating Custom Middleware In ASP.Net Core

老司机发车啦:https://github.com/SnailDev/SnailDev.NETCore2Learning

ASP.NET Core 2 学习笔记(三)中间件相关推荐

  1. asp.net core webAPI学习笔记(三)资源请求

    IDE 版本:Visual Studio 2017 15.9.7 asp.net core 版本 2.1.1 本文档说明需在 asp.net core webAPI学习笔记(一)项目搭建 的基础下进行 ...

  2. ASP.NET Core 2 学习笔记(七)路由

    ASP.NET Core通过路由(Routing)设定,将定义的URL规则找到相对应行为:当使用者Request的URL满足特定规则条件时,则自动对应到相符合的行为处理.从ASP.NET就已经存在的架 ...

  3. ASP.NET Core 2 学习笔记(四)依赖注入

    原文:ASP.NET Core 2 学习笔记(四)依赖注入 ASP.NET Core使用了大量的依赖注入(Dependency Injection, DI),把控制反转(Inversion Of Co ...

  4. 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(二)-- Web Api Demo

    在上一篇里,我已经建立了一个简单的Web-Demo应用程序.这一篇将记录将此Demo程序改造成一个Web Api应用程序. 一.添加ASP.NET Core MVC包 1. 在project.json ...

  5. 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(一)-- 起步

    一.安装Visual Studio Code 安装文件下载地址:VS Code,当前最新版本是1.3. 推荐安装最新版,因为附带Debug插件,支持在vs code上进行断点调试. 二.安装.Net ...

  6. 学习ASP.NET Core Razor 编程系列三——创建数据表及创建项目基本页面

    原文:学习ASP.NET Core Razor 编程系列三--创建数据表及创建项目基本页面 学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 ...

  7. ASP.NET MVC 2 学习笔记二: 表单的灵活提交

    ASP.NET MVC 2 学习笔记二:  表单的灵活提交 前面说到有做到公司内部的一个请假系统,用的是ASP.NET MVC 2+Entity Framework.虽然EF(Entity Frame ...

  8. Core Data 学习笔记(二)被管理对象模型

    为什么80%的码农都做不了架构师?>>>    目录 Core Data 学习笔记(一)框架简介 Core Data 学习笔记(二)被管理对象模型 Core Data 学习笔记(三) ...

  9. K8S 学习笔记三 核心技术 Helm nfs prometheus grafana 高可用集群部署 容器部署流程

    K8S 学习笔记三 核心技术 2.13 Helm 2.13.1 Helm 引入 2.13.2 使用 Helm 可以解决哪些问题 2.13.3 Helm 概述 2.13.4 Helm 的 3 个重要概念 ...

最新文章

  1. 修改mac系统的host文件 (一)
  2. C#教程8:面向对象编程【01】
  3. ionic overflow:auto失效
  4. 如何使用js动态显示或隐藏DIV
  5. 无光驱如何修复W7计算机,Win7电脑没有光驱怎么装系统?
  6. Java8————Base64
  7. 【Java】Socket实现的C/S模式半UI多人聊天程序
  8. Mac brew报错Error: The following directories are not writable by your user: /usr/local/share/man/man5
  9. ceph 代码分析 读_五大常见存储系统PK | Ceph、GlusterFS、MooseFS、HDFS、DRBD
  10. redis双写一致性问题
  11. ArcMap怎么导出shape文件到奥维互动地图
  12. 数据库变为可疑_SQL数据库可疑解决方法
  13. comps电磁场模拟软件_电力系统仿真软件综述说课.ppt
  14. UrlRewrite的使用
  15. js转换金钱为中文单位元、万元、亿元、万亿
  16. 关于Python爬取热搜的另一种方法
  17. CSS面试须知--盒子模型、浮动及定位
  18. notion自建服务器,【速报】Notion的特色「双向链接」方案来了,Synced Block 登场...
  19. 香港喜运佳,承载着太多的回忆
  20. 奋斗吧,程序员——第二十四章 想佳人、妆楼凝望,误几回、天际识归舟

热门文章

  1. springboot中使用redis详解
  2. 类型多种_五轴机床有很多种类型,你知道几种?
  3. python 函数调用 不允许关键字参数_你所不知道的Python|函数参数的演进之路
  4. java中间缓存变量机制_Java中间缓存变量机制
  5. kali怎么新建文本_甘特图怎么画?零基础快速绘制甘特图的软件
  6. 信息论与编码_哈夫曼编码
  7. linux tracepoint例子,tracepoint介绍
  8. android自定义下载框架,Android_DownloadUtil
  9. wps怎么投递简历发到boss直聘_BOSS直聘情色招聘:洗脑传销广告漫天飞,还陷虚假招聘...
  10. yolov3 推理所需要的时间_目标检测-番外五:YOLOv3-Plus