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.cs的Configure
对IApplicationBuilder
使用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=398940 public 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=398940 public 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=398940 public 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
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
AlexNet到底是什么?
投资家兼企业家Peter Thiel最喜欢的问题是:很少人赞同你的重要事实有哪些? 如果你在2010年向Geoffrey Hinton教授提出这个问题,他会回答道,卷积神经网络(CNN)有可能在解决图像分类问题上发挥巨大的作用。当时,该领域的研究人员并不重视这一言论,因为深度学习太平淡无奇了。 2010年ImageNet项目的大规模视觉识别挑战(ILSVRC)启动。 在随后的两年时间里,Alex Krizhevsky,Ilya Sutskever和Geoffrey E. Hinton的论文“利用深度卷积神经网络对图像进行分类”发表,这是前所未有的震撼!这篇论文以一种巧妙的手法打破了旧观念,开创了计算机视觉的新局面。 在接下来的几年里,多个团队将构建CNN体系结构,以期望超越人类层面的准确性。2012年论文中使用的架构通常被称为AlexNet,是用第一作者Alex Krizhevsky的名字命名。本文将回顾AlexNet的架构并讨论它的主要贡献。 输入 AlexNet是2012年ImageNet项目的大规模视觉识别挑战(ILSVRC)中的胜出者。AlexNet解决了图像分类的问题,输入是...
- 下一篇
三分钟学会如何在函数计算中使用 puppeteer
简介 使用 puppeteer 结合函数计算,可以快速的构建弹性的服务完成各种功能,包括: 生成网页截图或者 PDF 高级爬虫,可以爬取大量异步渲染内容的网页 模拟键盘输入、表单自动提交、登录网页等,实现 UI 自动化测试 捕获站点的时间线,以便追踪你的网站,帮助分析网站性能问题 接下来,将基于一个脚手架项目开发我们自己 puppeteer 项目。 下载项目 >>> git clone -o starter-kit https://github.com/awesome-fc/puppeteer-fc-starter-kit.git your_project_name 项目结构 ├── lib chrome headless 依赖的共享库,打包的时候,拷贝到打包项目的根目录下 ├── c
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS7设置SWAP分区,小内存服务器的救世主
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- 2048小游戏-低调大师作品