《ASP.NET Core技术内幕与项目实战》精简集-WebApi3.2:中间件Middleware
本节内容,涉及到7.6(P229-P242),以WebApi说明为主。主要NuGet包:无
一、图解中间件
1、服务器收到HTTP请求后,需要对请求进行一系列处理;当控制器中的操作方法完成后,也会对响应进行一系列处理。这一系列操作,如果全部硬编码到AspNetCore框架中,代码耦合度会很高。所以框架只完成HTTP请求响应调度和报文解析,其他可选工作由不同的中间件来完成。
2、在一个中间件中,有三部分组织,①前逻辑;②next方法;③后逻辑。HTTP请求到达服务器后,先由框架进行请求解析,然后进入第一个中间件,先执行前逻辑,然后由中间件自己决定是否执行next.Invoke(),如不执行,则请求中断,如执行,则请求进入下一个中间件。WebApi控制器的方法执行后,响应倒序从最后一个中间件开始,执行中间件的后逻辑。
3、每一次HTTP请求,框架会自动生成一个HttpContext类型的对象,称之为上下文,可以记录了请求路径、请求参数、请求客户端、响应报文、响应流、用户、自定义Items等信息。在中间件的前后逻辑和控制器中,均可以对HttpContext对象进行读写操作。
二、图解管道(pipeline)
1、上图中,每一个Use代表一个中间件,最后在Run中执行完请求,然后将响应返回。Use和Run组成一个HTTP请求的处理管道,而Map决定每个管道用于处理什么请求,Map("/test1")表示请求路径。如图所示,当服务器收到一个请求路径为"/test1"的HTTP请求时,就按管道1来处理。
2、我们用VS创建一个默认的WebApi项目时,在项目入口(Program.cs的Main方法)中,有很多“app.Use...”开头的代码,以及一个"app.Run()",这些不在Map定义的管道中的中间件,会默认处理所有请求。实际项目中,我们并不需要定义自己的Map管道,项目入口处定义的中间件,处理所有请求。也可以认为,AspNetCore默认为我们定义了一个处理所有请求的管道。
3、以下代码定义了一个处理“/test”请求的特殊管理
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); //指定处理“/test”路径请求的管道 app.Map("/test", async appBuilder => { //第一个中间件 appBuilder.Use(async (context, next) => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync("1 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("1 End<br/>"); }); //第二个中间件 appBuilder.Use(async (context, next) => { context.Response.ContentType = "text/html"; await context.Response.WriteAsync("2 Start<br/>"); await next.Invoke(); await context.Response.WriteAsync("2 End<br/>"); }); //Run终点 appBuilder.Run(async ctx => { await ctx.Response.WriteAsync("hello,it is run<br/>"); }); }); app.Run();
三、AspNetCore的常见中间件
var app = builder.Build(); if (app.Environment.IsDevelopment()) { //开发环境中,捕捉异常 app.UseDeveloperExceptionPage(); //OpenApi+Swagger中间件 app.UseSwagger(); app.UseSwaggerUI(); } app.UseExceptionHandler("/Error"); //生产环境中,捕捉异常 app.UseCors(); //跨域中间件,设置响应报文头允许跨域 app.UseHttpsRedirection(); //HTTP请求重定向到HTTPS app.UseCookiePolicy(); //Cookie策略中间件 app.UseSession(); //会话中间件,建立和维护会话状态 app.UseAuthentication(); //认证,哪些用户可以登陆访问 app.UseAuthorization(); //授权,登陆用户可以访问哪些资源 app.UseFileServer(); //默认文件、静态文件、目录浏览 app.MapControllers(); //控制器,包括路由 app.Run();
四、自定义一个简单的中间件
1 //定义一个中间类 2 //CheckMiddleware.cs 3 public class CheckMiddleware 4 { 5 private readonly RequestDelegate next; 6 public CheckMiddleware(RequestDelegate next) 7 { 8 this.next = next; 9 } 10 11 public async Task InvokeAsync(HttpContext context) 12 { 13 string pwd = context.Request.Query["password"]; 14 if (pwd == "123") 15 { 16 await next(context); 17 } 18 else 19 { 20 context.Response.StatusCode = 401; 21 } 22 } 23 } 24 25 26 //使用中间件 27 //Program.cs 28 var builder = WebApplication.CreateBuilder(args); 29 ...... 30 var app = builder.Build(); 31 ...... 32 app.Map("/test", async appBuilder => 33 { 34 appBuilder.UseMiddleware<CheckMiddleware>(); 35 appBuilder.Run(async context => 36 { 37 context.Response.ContentType = "text/html"; 38 context.Response.StatusCode = 200; 39 await context.Response.WriteAsync("<h1>success!</h1>"); 40 }); 41 }); 42 app.Run();
代码解读:
3-23行:中间件类是一个普通的类,没有继承和实现。但有几个固定成员:①注入RequestDelete对象;②返回值为Task的方法InvokeAsync,且参数为HttpContext
5-9行:注入RequestDelete对象,这个对象用来指向下一个中间件,如果不调用,则请求中止。调用前为中间件的前逻辑,调用后为后逻辑。
13-17行:从HttpContext对象里,读取请求的query参数password,如果密码为123,则执行下一个中间件,否则就报401错误
32-41行:当请求路径为"/test"时,执行自定义的管道,这个管道中有一个中间件CheckMiddleware,还有一个Run的处理逻辑
补充说明:
①除了Map方法之外,还有MapGet、MapPost、MapWhen等指定管道的方法,但实际项目中,如果不是开发框架,比较少用到Map
②大部分时间,我们极少需要自己定义中间件,一般都使用框架定义好的中间件,所以对框架提供的中间件要熟悉,另外要熟悉HttpContext对象的常用成员
③书中还有两个很精彩的案例:自己动手模仿WebApi框架、Markdown转换器中间件
特别说明:
1、本系列内容主要基于杨中科老师的书籍《ASP.NET Core技术内幕与项目实战》及配套的B站视频视频教程,同时会增加极少部分的小知识点
2、本系列教程主要目的是提炼知识点,追求快准狠,以求快速复习,如果说书籍学习的效率是视频的2倍,那么“简读系列”应该做到再快3-5倍
相关文章
- 关于.NET玩爬虫这些事
- 为什么 .NET的反射这么慢?
- 在ASP.NET Core中使用百度在线编辑器UEditor
- MVC路由自定义及视图找寻规则
- 构建高性能ASP.NET应用的12点建议
- 你了解AJAX吗?TA不是新编程语言而是WEB应用程序技术
- 从.net转型,聊聊最近一些面试,薪资和想法
- ASP.NET 5 开发者的五个阶段​​
- 让编程更轻松的 7 个 Visual Studio 扩展
- 对 ASP.NET 异步编程的一点理解
- 推荐 7 款好用的 Visual Studio 扩展
- 给ASP.NET MVC及WebApi添加路由优先级
- 10年.NET老程序员推荐的7个开发类工具
- 19 个必须知道的 Visual Studio 快捷键
- 迄今为止最全的.NET技术栈
- .NET中删除空白字符串的10大方法
- 详细的.Net并行编程高级教程--Parallel
- 如何用.NET生成二维码?
- .net程序员工作两年总结
- .NET中删除空白字符串的10大方法