博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ASP.NET Core 2 学习笔记(三)中间件
阅读量:5985 次
发布时间:2019-06-20

本文共 9562 字,大约阅读时间需要 31 分钟。

原文:

之前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=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
(); // ... }}

局部注册

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
(); } }}

注册Extension Middleware 的方式如下:

Startup.cs

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

参考

 

老司机发车啦:

转载地址:http://wwylx.baihongyu.com/

你可能感兴趣的文章
vue-cli 项目中绝对路径引用的相关资源 npm run build 后 打开页面报404错误
查看>>
动态规划入门-数字三角形(从朴素递归到各种优化)
查看>>
[04]CSS 颜色与度量单位
查看>>
BotBuilder Nodejs示例查看
查看>>
[CSAcademy]Exponential Game
查看>>
[HDU6252]Subway Chasing
查看>>
ES 使用小结
查看>>
Time模块简单学习
查看>>
在元素上执行鼠标双击操作
查看>>
Favicon
查看>>
Android打包
查看>>
jquery-ui autocomplete 自动完成功能
查看>>
ERROR: Unknown command 'crunch' 解决方法
查看>>
常用正则表达式
查看>>
给手机发送短信
查看>>
PHP编译安装
查看>>
eclipse快捷键
查看>>
java 基础6
查看>>
UI设计 - 首页(主页)的任务
查看>>
mongoose
查看>>