中间件是一种装配到应用管道以处理请求和响应的软件。 每个组件:

  • 选择是否将请求传递到管道中的下一个组件。
  • 可在调用管道中的下一个组件前后执行工作。

请求委托(Request delegates)用于生成请求管道。 请求委托处理每个 HTTP 请求。

每个中间件扩展方法都通过 Microsoft.AspNetCore.Builder 命名空间在 IApplicationBuilder 上公开。

public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
});
}
}

中间件(Middleware)的作用

我们知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终到达我们写的代码中。那么中间件就是在应用程序管道中的一个组件,用来拦截请求过程进行一些其他处理和响应。中间件可以有很多个,每一个中间件都可以对管道中的请求进行拦截,它可以决定是否将请求转移给下一个中间件。

asp.net core 提供了IApplicationBuilder接口来让把中间件注册到asp.net的管道请求当中去,中间件是一个典型的AOP应用。 下面是一个微软官方的一个中间件管道请求图:

可以看到,每一个中间件都都可以在请求之前和之后进行操作。请求处理完成之后传递给下一个请求。

中间件(Middleware)和过滤器(Filter)的区别

熟悉MVC框架的同学应该知道,MVC也提供了5大过滤器供我们用来处理请求前后需要执行的代码。分别是AuthenticationFilter,AuthorizationFilter,ActionFilter,ExceptionFilter,ResultFilter。

根据描述,可以看出中间件和过滤器的功能类似,那么他们有什么区别?为什么又要搞一个中间件呢?

其实,过滤器和中间件他们的关注点是不一样的,也就是说职责不一样,干的事情就不一样。

同作为两个AOP利器,过滤器更贴合业务,它关注于应用程序本身,比如你看ActionFilter 和 ResultFilter,它都直接和你的Action,ActionResult交互了,是不是离你很近的感觉,那我有一些比如对我的输出结果进行格式化啦,对我的请求的ViewModel进行数据验证啦,肯定就是用Filter无疑了。它是MVC的一部分,它可以拦截到你Action上下文的一些信息,而中间件是没有这个能力的。

什么情况我们需要中间件

那么,何时使用中间件呢?我的理解是在我们的应用程序当中和业务关系不大的一些需要在管道中做的事情可以使用,比如身份验证,Session存储,日志记录等。其实我们的 asp.net core项目中本身已经包含了很多个中间件。

中间件的运行方式

默认情况下,中间件的执行顺序根据Startup.cs文件中,在public void Configure(IApplicationBuilder app){} 方法中注册的先后顺序执行。

大概有3种方式可以在管道中注册"中间件"

app.Use()IApplicationBuilder接口原生提供,注册等都用它。

app.Run() ,是一个扩展方法,它需要一个RequestDelegate委托,里面包含了Http的上下文信息,没有next参数,因为它总是在管道最后一步执行。

app.Map(),也是一个扩展方法,类似于MVC的路由,用途一般是一些特殊请求路径的处理。如:www.example.com/token 等。

app.Run()

app.Run(async context =>
{
await context.Response.WriteAsync("Hello, World!");
}); //-------------------Run定义--------------------------
//Run传入一个RequestDelegate
public static class RunExtensions
{
public static void Run(this IApplicationBuilder app, RequestDelegate handler);
} //RequestDelegate就是一个委托
public delegate Task RequestDelegate(HttpContext context);

app.Use();

app.Use(async (context, next) =>
{
await context.Response.WriteAsync(" ===>1.start.Hello World!");
await next();
await context.Response.WriteAsync(" ===>1.end.Hello World!");
});
//-------------------Use定义-------------------------- public static IApplicationBuilder Use(this IApplicationBuilder app,
Func<HttpContext, Func<Task>, Task> middleware);

案例:

           app.Use(async (context, next) =>
{
await context.Response.WriteAsync(" ===>1.start.Hello World!");
await next();
await context.Response.WriteAsync(" ===>1.end.Hello World!");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync(" ===>2.start.Hello World!");
await next();
await context.Response.WriteAsync(" ===>2.end.Hello World!");
});
app.Use(async (context, next) =>
{
await context.Response.WriteAsync(" ===>3.start.Hello World!");
//await next();
await context.Response.WriteAsync(" ===>3.end.Hello World!");
});

输出结果:

===>1.start.Hello World!   ===>2.start.Hello World!   ===>3.start.Hello World!   ===>3.end.Hello World!   ===>2.end.Hello World!   ===>1.end.Hello World!

如果这里 await next(); 没有注释

直接网络连接异常、网站服务器失去响应

因为,context.Response 里面有数据,所以 UseMvc时,判断有数据就不加载了。

app.Map()

public void Configure(IApplicationBuilder app)
{
app.Use(async (context, next) =>
{
await context.Response.WriteAsync(" ===>1.start.Hello World!");
await next();
await context.Response.WriteAsync(" ===>1.end.Hello World!");
}); app.Map("/map1", HandleMapTest1); app.Map("/map2", HandleMapTest2); app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
HandleBranch); app.Run(async context =>
{
await context.Response.WriteAsync(" ===>Hello from non-Map delegate. <p>");
});
} private static void HandleMapTest1(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync(" ===>Map Test 1");
});
} private static void HandleMapTest2(IApplicationBuilder app)
{
app.Run(async context =>
{
await context.Response.WriteAsync(" ===>Map Test 2");
});
} private static void HandleBranch(IApplicationBuilder app)
{
app.Run(async context =>
{
var branchVer = context.Request.Query["branch"];
await context.Response.WriteAsync($" ===>Branch used = {branchVer}");
});
}
请求 响应
https://localhost:5001/ ===>1.start.Hello World! ===>Hello from non-Map delegate.

===>1.end.Hello World!

https://localhost:5001/map1 ===>1.start.Hello World! ===>Map Test 1 ===>1.end.Hello World!
https://localhost:5001/map2 ===>1.start.Hello World! ===>Map Test 2 ===>1.end.Hello World!
https://localhost:5001/?branch=master ===>1.start.Hello World! ===>Branch used = master ===>1.end.Hello World!

MapWhen 基于给定谓词的结果创建请求管道分支。 Func<HttpContext, bool> 类型的任何谓词均可用于将请求映射到管道的新分支。

public static IApplicationBuilder MapWhen(this IApplicationBuilder app,
Func<HttpContext, bool> predicate,
Action<IApplicationBuilder> configuration);

封装中间件

上面的Run,Map内部也是调用的Use,算是对IApplicationBuilder接口扩充,如果你觉得名字都不够准确,那么下面这个扩展方法就是正宗的注册中间件的了,也是功能最强大的。

app.UseMiddleware<>(),没错,就是这个了。 为什么说功能强大呢?是因为它不但提供了注册中间件的功能,还提供了依赖注入(DI)的功能,以后大部分情况就用它了。

namespace IdentityDemo2.Middleware
{
public class StartMiddleware
{
private readonly RequestDelegate _next; public StartMiddleware(RequestDelegate next)
{
_next = next;
} public async Task InvokeAsync(HttpContext context)
{
await context.Response.WriteAsync(" ===>StartMiddleware"); // Call the next delegate/middleware in the pipeline
await _next(context);
}
} public static class StartMiddlewareExtensions
{
public static IApplicationBuilder UseStart(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<StartMiddleware>();
}
}
}

以下代码通过 Startup.Configure 调用中间件:

public class Startup
{
public void Configure(IApplicationBuilder app)
{
app.UseMiddleware<StartMiddleware>(); //写法1。
app.UseStart(); //写法2。 app.Run(async (context) =>
{
await context.Response.WriteAsync(
$"Hello {CultureInfo.CurrentCulture.DisplayName}");
}); }
}

参考:

zhulongxi,net core 中间件详解及项目实战

asp.net core 中间件应用的更多相关文章

  1. ASP.NET Core 中间件Diagnostics使用

    ASP.NET Core 中间件(Middleware)Diagnostics使用.对于中间件的介绍可以查看之前的文章ASP.NET Core 开发-中间件(Middleware). Diagnost ...

  2. ASP.NET Core中间件(Middleware)实现WCF SOAP服务端解析

    ASP.NET Core中间件(Middleware)进阶学习实现SOAP 解析. 本篇将介绍实现ASP.NET Core SOAP服务端解析,而不是ASP.NET Core整个WCF host. 因 ...

  3. [转]ASP.NET Core 中间件详解及项目实战

    本文转自:http://www.cnblogs.com/savorboard/p/5586229.html 前言 在上篇文章主要介绍了DotNetCore项目状况,本篇文章是我们在开发自己的项目中实际 ...

  4. 如何一秒钟从头构建一个 ASP.NET Core 中间件

    前言 其实地上本没有路,走的人多了,也便成了路. -- 鲁迅 就像上面鲁迅说的那样,其实在我们开发中间件的过程中,微软并没有制定一些策略或者文档来约束你如何编写一个中间件程序, 但是其中却存在者一些最 ...

  5. ASP.NET Core中间件实现分布式 Session

    1. ASP.NET Core中间件详解 1.1. 中间件原理 1.1.1. 什么是中间件 1.1.2. 中间件执行过程 1.1.3. 中间件的配置 1.2. 依赖注入中间件 1.3. Cookies ...

  6. ASP.NET Core 入门教程 9、ASP.NET Core 中间件(Middleware)入门

    一.前言 1.本教程主要内容 ASP.NET Core 中间件介绍 通过自定义 ASP.NET Core 中间件实现请求验签 2.本教程环境信息 软件/环境 说明 操作系统 Windows 10 SD ...

  7. ASP.NETCore学习记录(二) —— ASP.NET Core 中间件

    ASP.NET Core 中间件 目录: 什么是中间件 ? IApplicationBuilder 使用 IApplicationBuilder 创建中间件 Run.Map 与 Use 方法 实战中间 ...

  8. ASP.NET Core 中间件基本用法

    ASP.NET Core 中间件 ASP.NET Core的处理流程是一个管道,而中间件是装配到管道中的用于处理请求和响应的组件.中间件按照装配的先后顺序执行,并决定是否进入下一个组件.中间件管道的处 ...

  9. (4)ASP.NET Core 中间件

    1.前言 整个HTTP Request请求跟HTTP Response返回结果之间的处理流程是一个请求管道(request pipeline).而中间件(middleware)则是一种装配到请求管道以 ...

  10. ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 中间件 上一章节中,我们我们有讲到 Startup 类中的 Confi ...

随机推荐

  1. Linux查看本机IP:curl cip.cc

    curl http://members.3322.org/dyndns/getip curl ip.6655.com/ip.aspx curl ifconfig.me curl icanhazip.c ...

  2. python3+requests库框架设计06-测试脚本

    在项目下新建TestCase文件夹,然后新建.py文件在文件中写关于接口具体的测试脚本,一般我喜欢按照模块来分,一个模块一个.py文件,建议以test开头命名文件 把配置文件改成这样 url:http ...

  3. codeforces 38G - Queue splay伸展树

    题目 https://codeforces.com/problemset/problem/38/G 题意: 一些人按顺序进入队列,每个人有两个属性,地位$A$和能力$C$ 每个人进入时都在队尾,并最多 ...

  4. POJ3580 SuperMemo splay伸展树,区间操作

    题意:实现一种数据结构,支持对一个数列的 6 种操作:第 x 个数到第 y 个数之间的数每个加 D:第 x 个数到第 y 个数之间全部数翻转:第 x 个数到第 y 个数之间的数,向后循环流动 c 次, ...

  5. zabbix3.0.4使用percona-monitoring-plugins插件来监控mysql5.6的详细实现过程

    zabbix3.0.4使用percona-monitoring-plugins插件来监控mysql5.6的详细实现过程 因为Zabbix自带的MySQL监控没有提供可以直接使用的Key,所以一般不采用 ...

  6. maven:手动安装JAR到本地仓库

    mvn install:install-file -DgroupId=com.test -DartifactId=test -Dversion=1.0.0 -Dpackaging=jar -Dfile ...

  7. Python Redis pipeline操作

    Redis是建立在TCP协议基础上的CS架构,客户端client对redis server采取请求响应的方式交互. 一般来说客户端从提交请求到得到服务器相应,需要传送两个tcp报文. 设想这样的一个场 ...

  8. GridView的stretchMode属性

    stretchMode属性值的作用是设置GridView中的条目以什么缩放模式去填充剩余空间.参数stretchMode 可选值为:none,spacingWidth,columnWidth, spa ...

  9. vuforia unity 识别图片出模型

    ARCamera设置: 然后设置ImageTarge

  10. 本文转自 MyEclipse 2015反编译插件安装

    本文转自MyEclipse 2015反编译插件安装 分享一下下载插件的地址,百度网盘:链接:http://pan.baidu.com/s/1nturiAH 密码:yk73 其次:我来说下具体操作步骤: ...