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

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

请求委托(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. VDB R&D

    VDB Data value visualize: 结论从houdini得知. API常用文字: interior:内部 Narrow-band:窄带 background:窄带外 SDF: XY p ...

  2. js知识巩固

    1.数组操作中使用splice和slice进行删除数组的区别! splice会对原数组进行操作,返回的是被删除元素组成的数组,原数组会被进行改变即变成删除后的数组,用于删除列表中的元素,arr.spl ...

  3. weblogic和was的巡检报告模板

    weblogic巡检报告模板  https://max.book118.com/html/2017/0710/121553357.shtm 用jrockit How to tell Our WebLo ...

  4. iptables防火墙端口操作

    1.将开放的端口写入iptables中,在终端中输入命令: /sbin/iptables -I INPUT -p tcp --dport -j ACCEPT 2.保存上一步的修改内容,输入命令: /e ...

  5. 解决Windows 10笔记本接显示器分屏后没有声音的问题

    Windows 10 版本号:17763.292 1.首先右键点击任务栏托盘中的[扬声器]图标,选择[声音],如下图所示. 2.选择[播放],然后选择[扬声器],再点击[设为默认值],如下所示. 3. ...

  6. tomcat session Memcache 共享

    背景 这次做的这个项目并发还真是挺高,单表一天产生百万条记录不在话下.结果导致运行过程中经常丢失数据,卡.慢等.开来终于要搞一次负载均衡了,之前实验学习了不少,但是没有在项目中实际用过,因为并发量不大 ...

  7. nginx指定文件路径有两种方式root和alias

    背景 一直没明白这个配置啥意思,反正凑合用吧,不过老凑合总不是个事,没搞明白更容易忘,别人问还答不上来.反正也很简单,就搞明白点记下来. 知识点 root实例: location ^~ /t/ { r ...

  8. less/sass 基础base文件

    less less-base.less文件展示: //清除标签默认样式; .label(){ ;;;_background-image:url(n1othing.txt)} ;;; font-size ...

  9. 缓存系列之二:CDN与其他层面缓存

    缓存系列之二:CDN与其他层面缓存 一:内容分发网络(Content Delivery Network),通过将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服 ...

  10. Windows系统下安装dig命令

    dig 是一个 Linux 下用来 DNS 查询信息的工具,全称是Domain Information Groper,与 nslookup 类似,但比 nslookup 功能更强大.Windows 下 ...