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

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

请求委托(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. 【ARTS】01_20_左耳听风-20190325~20190331

    zz## ARTS: Algrothm: leetcode算法题目 Review: 阅读并且点评一篇英文技术文章 Tip/Techni: 学习一个技术技巧 Share: 分享一篇有观点和思考的技术文章 ...

  2. Keepalived详解(三):Keepalived基础功能应用实例【转】

    Keepalived基础功能应用实例: 1.Keepalived基础HA功能演示: 在默认情况下,Keepalived可以实现对系统死机.网络异常及Keepalived本身进行监控,也就是说当系统出现 ...

  3. Windows PowerShell 入門(8)-関数編3

    この連載では.Microsoftが提供している新しいシェル.Windows PowerShellの使い方を解説します.今回は.フィルタ.スクリプトブロック.変数のスコープについて取り上げます. はじめ ...

  4. 打印机wifi

    给人修理了半天共享打印机问题,连接不上,被共享机为32位xp系统,共享机为64位win7系统,共享时无法安装驱动,最后知道打印机具备连接wifi功能,然后用官网驱动连接打印机即可.out了,现在打印机 ...

  5. 转载:Eureka 开发时快速剔除失效服务

    原文地址:https://www.cnblogs.com/flying607/p/8494568.html 服务端配置: # 关闭保护机制 eureka.server.enable-self-pres ...

  6. android端 socket长连接 架构

    看过包建强的<App研发录>之后对其中的基础Activity类封装感到惊讶,一直想找一种方式去解决关于app中使用socket长连接问题,如何实现简易的封装来达到主活动中涉及socket相 ...

  7. linux学习之uniq

    uniq最经常用的是统计次数,通常先排序,然后uniq  -c cat a.txt |sort -nr |uniq -c

  8. Java 的 Api 文档生成工具 JApiDocs 程序文档工具

    JApiDocs 详细介绍 简介 JApiDocs 是一个符合 Java 编程习惯的 Api 文档生成工具.最大程度地利用 Java 的语法特性,你只管用心设计好接口,添加必要的注释,JApiDocs ...

  9. Confluence 6 为搜索引擎隐藏外部链接

    为搜索引擎隐藏外部链接能够避免向你的站点添加垃圾信息.如果你启用了这个选项的话,任何插入到页面中的 URLs 和评论将会赋予 'nofollow' 属性,这个属性将会禁止搜索引擎进行索引.  快捷链接 ...

  10. Confluence 6 代理和 HTTPS 设置连接器

    很多用户选择将 Confluence 运行在反向代理的后面,同时还启用了 HTTPS.将你的的 Confluence 反向代理配置正确就显得非常必要了,并且能够避免后期在使用 Confluence 遇 ...