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

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

请求委托(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. [转] Torch中实现mini-batch RNN

    工作中需要把一个SGD的LSTM改造成mini-batch的LSTM, 两篇比较有用的博文,转载mark https://zhuanlan.zhihu.com/p/34418001 http://ww ...

  2. python 各种推导式玩法

    推导式套路 除了最简单的列表推导式和生成器表达式,其实还有字典推导式.集合推导式等等. 下面是一个以列表推导式为例的推导式详细格式,同样适用于其他推导式. variable = [out_exp_re ...

  3. 从MySQL中导入数据到MongoDB中

    从sql中导出需要的数据为csv格式的数据 select field1,field2,...,fieldn from TABLE into outfile '/test.csv' fields ter ...

  4. 在Centos7 上安装SVN

    https://blog.csdn.net/crossangles_2017/article/details/78553266 1.安装 使用yum安装非常简单: yum install subver ...

  5. 所有ORM操作 (第二版)

    ####################################################################### # PUBLIC METHODS THAT ALTER ...

  6. [转]ASCII码表及扩展ASCII码表,方便查阅

    ASCII码表可以看成由三部分组成: 第一部分:由00H到1FH共32个,一般用来通讯或作为控制之用.有些可以显示在屏幕上,有些则不能显示,但能看到其效果(如换行.退格).如下表: 第二部分:是由20 ...

  7. 14)django-模板(计数器)

    模块中for循环自带计数器. 使用场景:表格数据相增加序列号. 问:可以使用表的自增加序列做为序列号,但是这个存在个问题,即表中数据被删除,则会出现序列不连续. 1)每个循环都有6个公共方法,双循环有 ...

  8. 图解Metrics, tracing, and logging

    Logging,Metrics 和 Tracing   最近在看Gophercon大会PPT的时候无意中看到了关于Metrics,Tracing和Logging相关的一篇文章,凑巧这些我基本都接触过, ...

  9. hadoop常用命令详细解释

    hadoop命令分为2级,在linux命令行中输入hadoop,会提示输入规则 Usage: hadoop [--config confdir] COMMAND where COMMAND is on ...

  10. windows+mysql集群搭建-三分钟搞定集群

    注:本文来源:  陈晓婵   <  windows+mysql集群搭建-三分钟搞定集群   > 一:mysql集群搭建教程-基础篇 计算机一级考试系统要用集群,目标是把集群搭建起来,保证一 ...