最近博客更新频率慢了些,原因有三:

其一,最近老周每星期六都录 ASP.NET Core 的直播,有些内容在视频里讲过,就不太想在博客里面重复。有兴趣的话可以去老周的微博看,或者去一直播,直播帐号与微博帐号是绑定的;

其二,最近老周是有些忙,但不是忙写代码的事情。而是忙着“寻宝藏”。

其三,每个星期至少也要抽出一天的时间,跟妹子出去浪。准确地说,应该叫对象(Object),是通过构造函数认识的,已经顺利运行有五个月了。目前状态良好,内存占用小,不烧 CPU。性能好,不吃硬件。

好了,屁话不多说了。今天说说如何向中间件传参数的事。

首先,用宇宙中最通俗的语言介绍一下啥是中间件。浏览器或客户端向服务器发出请求后,HTTP 请求会进入通信管道,然后由一个个中间件来进行处理,A 处理完了,交给 B;B 处理完了再交给 C……所有中间件就串成一条链,直到最后一个中间件(HTTP 404)。处理完后就把结果返回给调用者。

所以说,中间件就是一个处理 HTTP 请求的“零件”,比如,你可以定义一个中间件,对请求中的某些数据进行解密或者验证。或者,你可以定义一个中间件来添加自己定义的 HTTP 头。

中间件在代码中由一个 RequestDelegate 委托来表示,该委托声明如下。

delegate System.Threading.Tasks.Task RequestDelegate(Microsoft.AspNetCore.Http.HttpContext context)

HttpContext 可以保持整个 HTTP 请求上下文中的数据与状态,并且在调用每一个中间件时,会将自身传递过去。返回类型为 Task,表示支持异步等待。

对于代码简单的中间件,可以直接 Use 扩展方法,比如这样。

            app.Use(async (context, next) =>
{
context.Response.Headers.Add("key", "no key");
await next();
});

next 是指处理链条上的下一个中间件,如果没特殊事情,在当前代码处理完后应该调用下一个中间件。当然,如果没有必要调用下一个中间件,那可以不调用 next,这样,整个 HTTP 通信管道就中止了。

但是,如果中间件逻辑多,代码多,而且又要接收参数的话,那就应该用一个类来封装。封装的时候一定要注意相关的约定。

中间件必须包含一个 Invoke 或 InvokeAsync 方法,方法的参数为 HttpContext,返回类型为 Task。

为什么要这个约定呢?你看看刚刚那个 RequestDelegate 委托。委托类型的实例是不是有个 Invoke 方法?这就对了,大概为了方便记忆,所以代码约定也使用了 Invoke 这名字。在运行的时候,框架会在中间件类中寻找名字为 Invoke 或 InvokeAsync 的方法。所以,要想自定义的中间件类起作用,你应该遵守这个约定。

我们今天讨论的重点是向中间件传参数,要能传参的话,就必须写一个中间件类。先说说,怎么传参。方法有二。

一、IApplicationBuilder 的 UseMiddleware 扩展方法,此方法的参数列表中,最后一个是加了 params 关键字的 object 数组。这个就是用来传参数的,而且参数的个数是不确定的。传入的参数从中间件类的构造函数中接收。

二、通过依赖注入自动获取。虽然中间件类的构造函数可以接收注入对象,但是,不推荐在这里接收注入对象,因为这样会改变注入对象的生命周期。由于中间件类在运行阶段只实例化一次,故它的生命周期应与应用程序相等。所以,如果通过构造函数获取注入的话,由于注入对象长期存在引用,使得服务容器无法释放它。如果注入对象是用 AddTransient 方法添加到服务集合中,本应该每次使用后释放,但由于实例被引用,就会导致生命周期变得与应用程序同等,所以,不应该在中间件类的构造函数中来注入,而应该在 Invoke 或 InvokeAsync 方法中进行注入。

来来来,动手,咱们用实例来学习,效果会番十倍的。

先写一个中间件类。

    public class DemoMiddleware
{
RequestDelegate _next;
double mx, my; public DemoMiddleware(RequestDelegate next, double x, double y)
{
_next = next;
mx = x;
my = y;
} public async Task InvokeAsync(HttpContext context)
{
double r = mx + my;
context.Response.Headers["Compute-Result"] = $"{mx} + {my} = {r}";
await _next(context);
}
}

注意啊各位,中间件类的构造函数,一般都要一个 RequestDelegate 的参数,干吗用的呢?就是让你可以调用下一个中间件,它代表的是链条上的下一个中间件。

两个 double 类型的参数才是我们真正要传的参数。在 InvokeAsync 方法中,我做了一个简单处理,把两个参数的值相加,然后通过 HTTP 头返回给客户端。

为了使下一个中间件能被调用,记得在 InvokeAsync 方法的最后调用一下 _next 字段。

现在,回到 Startup 类,找到 Configure 方法,我们使用刚刚定义的中间件类。

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
…… app.UseMiddleware<DemoMiddleware>(15.33d, 8.96d);
}

参数就是通过 UseMiddleware 方法来传递给中间件类的,有几个就传几个,该什么类型就什么类型,因为参数签名是 object 类型,有容乃大,它能兼容所有类型。

现在我们来测试一下。运行之后,你发现浏览器得到的是 404,对的,前面老周说了,中间件链条的最后一个中间件就是 404。我们没有向客户端回写任何内容,所以返回 404 太正常了。但是,代码其实是成功执行了的。

你可以打开抓包工具(比如 F12 工具里面就有),然后刷新一下,随后你去看一下返回消息的 Http 头。

看到了吧,说明中间件是执行了的。

下面,我们用依赖注入,在中间件中获取参数。

    public class Demo2Middleware
{
RequestDelegate _next; public Demo2Middleware(RequestDelegate next)
{
_next = next;
} public async Task Invoke(HttpContext context, IHostingEnvironment env)
{
context.Response.Headers["app-name"] = env.ApplicationName;
context.Response.Headers["env-name"] = env.EnvironmentName;
await _next(context);
}
}

在 Invoke 方法中,第一个参数是 HttpContext,这个东东是必须的,然后后面我们获取一个 IHostingEnvironment,这个在应用程序初始化时由框架自动添加到服务容器中,它会自动注入到 Invoke 方法中。在上面代码中,我只是把应用名称和运行环境名称添加到 HTTP 头中。

随后在 Startup 类的 Configure 方法中,也用上这个中间件。

       app.UseMiddleware<Demo2Middleware>();

运行之后,刷新浏览器,再抓包,你就看到在 Http Header 集合中多了几个东东。

爽吧,中间件也顺利执行了。

其实,你仔细一看就会发现,这个 Invoke / InvokeAsync 方法的注入方式与 Startup 类的 Configure 方法是一样的。Configure 方法的第一个参数是必须的,型类为 IApplicationBuilder,后面的参数就是注入的。

好了,向中间件传参数的两种方法都介绍完了。

最后,顺便说一下,“五一”假期前老周可能会直播一次 ASP.NET Core ,但不保证会开播,如果这几天没弄的话,就要等“五一”假期之后再开播。

【ASP.NET Core】给中间件传参数的方法的更多相关文章

  1. 如何传递参数给ASP.NET Core的中间件(Middleware)

    问题描述 当我们在ASP.NET Core中定义和使用中间件(Middleware)的时候,有什么好的办法可以给中间件传参数吗? 解决方案 在ASP.NET Core项目中添加一个POCO类来传递参数 ...

  2. asp.net core mvc 中间件之WebpackDevMiddleware

    asp.net core mvc 中间件之WebpackDevMiddleware WebpackDevMiddleware中间件主要用于开发SPA应用,启用Webpack,增强网页开发体验.好吧,你 ...

  3. asp.net core mvc 中间件之路由

    asp.net core mvc 中间件之路由 路由中间件 首先看路由中间件的源码 先用httpContext实例化一个路由上下文,然后把中间件接收到的路由添加到路由上下文的路由集合 然后把路由上下文 ...

  4. ASP.NET Core:中间件

    一.什么是中间件 我们都知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终才会到达我们写的代码中.而中间件就是用于组成应用程序管道来处理请求和响应的 ...

  5. 如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容?

    原文:如何在ASP.NET Core自定义中间件中读取Request.Body和Response.Body的内容? 文章名称: 如何在ASP.NET Core自定义中间件读取Request.Body和 ...

  6. ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目

    ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml)   我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...

  7. asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。

    原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...

  8. ASP.NET Core路由中间件[3]: 终结点(Endpoint)

    到目前为止,ASP.NET Core提供了两种不同的路由解决方案.传统的路由系统以IRouter对象为核心,我们姑且将其称为IRouter路由.本章介绍的是最早发布于ASP.NET Core 2.2中 ...

  9. ASP.NET Core路由中间件[2]: 路由模式

    一个Web应用本质上体现为一组终结点的集合.终结点则体现为一个暴露在网络中可供外界采用HTTP协议调用的服务,路由的作用就是建立一个请求URL模式与对应终结点之间的映射关系.借助这个映射关系,客户端可 ...

随机推荐

  1. hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(1)安装jdk

    一.文件准备 下载jdk-8u131-linux-x64.tar.gz 二.工具准备 2.1 Xshell 2.2 Xftp 三.操作步骤 3.1 解压文件: $ tar zxvf jdk-8u131 ...

  2. Spring-Boot导入配置文件与取值

    前言: springboot简化了大量配置文件,但是必要时还是需要导入配置文件的,比如dubbo,此处简记之. 正文: 所有的配置文件引入都是使用注解在类上进行引入的,常用的有两种注解@Propert ...

  3. Python之格式化输出,初始编码以及运算符

    一.题型 1.使用while循环输入 1 2 3 4 5 6  8 9 10 count = 0 while count < 10: count += 1   #count = count + ...

  4. c++中的类之构造函数

    一.构造函数的缘由 本文我们主要来讲解c++中类的构造函数,其中涉及了深拷贝和浅拷贝的问题,这也是在面试笔试中经常会碰到的问题.如果您是第一次听说构造函数,可能会觉得这个名字有点高大上,而它却和实际中 ...

  5. AQS源码阅读笔记(一)

    AQS源码阅读笔记 先看下这个类张非常重要的一个静态内部类Node.如下: static final class Node { //表示当前节点以共享模式等待锁 static final Node S ...

  6. 尼姆博弈(Nimm's Game)

    题型: 有3堆各若干个物品,两个人轮流从某一堆取任意多的物品,规定每次至少取1个,多者不限,最后取光者得胜. 思路 首先自己想一下,就会发现只要最后剩两堆物品一样多(不为零),第三堆为零,那面对这种局 ...

  7. TensorFlow-Slim使用方法说明

    翻译自:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/slim TensorFlow-Slim TF- ...

  8. python如何转换word格式、读取word内容、转成html

    # python如何转换word格式.读取word内容.转成html? import docx from win32com import client as wc # 首先将doc转换成docx wo ...

  9. canvas实现的粒子效果

    前言:我的这个share很简单,没什么技术水准,主要是我自己觉得canvas这个标签很cool!,简单实用又能装X,而且又能实现很多看起来很炫的东西. 一 关于canvas <canvas> ...

  10. Linux查看文件指定某些行的内容

    查看从第5行开始的100行内容,并把结果重定向到一个新的文件 cat file | tail -n +5 | head -n 100 > newfile.txt 查看第5行到100行的内容,并把 ...