ASP.NET Core中HTTP管道和中间件的二三事

640?wx_fmt=gif

本文出自《从零开始学ASP.NET CORE MVC》
推荐文章:中间件是什么?在.NET Core中的工作原理又是怎样的呢?

配置ASP.NET Core请求(Request)处理管道

640?wx_fmt=png

在本视频中,我们将讨论使用中间件组件为asp.net core 应用程序配置请求处理管道。

作为应用程序启动的一部分,我们要在Configure()方法中设置请求处理管道

public class Startup
{

public void ConfigureServices(IServiceCollection services)
{
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}

}

目前我们的代码中有2个中间件在管道中 :UseDeveloperExceptionPage()方法Run()方法

UseDeveloperExceptionPage 中间件:顾名思义,如果存在异常并且环境是Development,此中间件会被调用,显示开发异常页面。 我们将在后面的视频中讨论这个DeveloperExceptionPage中间件环境变量的使用

第二个中间件是注册Run()方法到管道中,它只能处理将一个信息传入Response对象。 目前,它是一个响应每个请求的中间件,返回Hello world。
在这种情况下,无论您的请求路径是什么。 所有请求都会被这个中间件所处理,我们得到的返回值都是这个中间件调用Response对象,返回的string类型的字符串。
返回的值是纯文本而不是html。 我们可以通过检查页面源代码来确认这一点。
可以看到,我们在源代码中没有任何html标记。 只是纯文本。

即使您现在创建一个为52abp.html的文件,并且您在请求中包含该文件的路径,我们的应用程序也无法返回该静态文件。 这是因为,目前我们的请求处理管道没有可以提供静态文件的中间件,如html文件,图像,CSS和JavaScript文件
在后面的课程中,我们将添加所需的中间件以便能够提供静态文件。

研究下 Configure()方法中的代码。

640?wx_fmt=png

app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});

代码说明:

  • 我们调用Run() 方法添加中间件到请求处理管道中。

  • 如果将鼠标悬停在Run()方法上,则可以从 智能提示中看到Run()方法是作为IApplicationBuilder接口的扩展方法实现的。这就是我们能够在IApplicationBuilder对象应用程序上调用此Run()方法的原因。

  • 我们传递给Run()方法的参数是一个RequestDelegate,我们可以从智能提示中看到它。

  • RequestDelegate是一个作为HttpContext对象的参数委托。

  • 通过这个HttpContext对象,中间件可以访问传入的http请求和传出的http响应。

  • 目前,我们使用lambda将请求,它通过委托内联的方式作为匿名方法传递,所以很多人都说lambda表达式是一种特殊的委托。如果你听不明白lambda表达式,委托,及内联,你可以参考学习:

    • 委托(delegate)

    • Lambda简介 ,或者等我录制C#的基础视频吧。

  • 使用Run()扩展方法,我们只能将一个终端中间件添加到请求管道。

  • 终端中间件是我们之前已经说到过,他会使管道短路,不会去调用下一个中间件。


研究下面的代码

640?wx_fmt=png

app.Run(async (context) =>
{
await context.Response.WriteAsync("从第一个中间件中打印Hello World");
});

app.Run(async (context) =>
{
await context.Response.WriteAsync("从第二个中间件中打印Hello World");
});
  • 我们使用Run()方法注册了2个中间件。

  • 运行此项目时,我们只看到第一个中间件的响应,有返回值。

  • 我们没有看到第二个中间件的响应。

  • 这是因为,使用Run()方法注册的中间件无法调用管道中的下一个中间件。

  • 因此,我们使用Run()方法注册的中间件是终端中间件

如果您希望中间件能够调用管道中的下一个中间件,则使用Use()方法注册中间件,如下所示。

app.Use(async (context, next) =>
{
await context.Response.WriteAsync("从第一个中间件中打印Hello World");
await next();
});

app.Run(async (context) =>
{
await context.Response.WriteAsync("从第二个中间件中打印Hello World");
});

注意,Use()方法有2个参数。第一个参数是HttpContext上下文对象,第二个参数是Func类型,即它是代表管道中下一个中间件的通用委托。

我们再看看以下代码

640?wx_fmt=png

public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILogger<Startup> logger)
{
app.Use(async (context, next) =>
{
logger.LogInformation("MW1:传入请求");
await next();
logger.LogInformation("MW1:传出响应");
});

app.Use(async (context, next) =>
{
logger.LogInformation("MW2: 传入请求");
await next();
logger.LogInformation("MW2: 传出响应");
});

app.Run(async (context) =>
{
await context.Response.WriteAsync("MW3: 处理请求并生成响应");
logger.LogInformation("MW3: 处理请求并生成响应");
});
}
  • ILogger < Startup >被注入到Configure()方法中

  • Main()方法调用的CreateDefaultBuilder()配置日志记录

  • 您可以通过查看在GitHub的源代码验证这一点
    :https://github.com/aspnet/MetaPackages/blob/release/2.2/src/Microsoft.AspNetCore/WebHost.cs

  • 检查方法ConfigureLogging(),* 您会发现,ILogger配置了Console,Debug和EventSource三种.

  • 我们使用依赖注入的方式将ILogger记录到系统中。

  • 如果使用.NET Core CLI运行项目,则可以在“控制台”窗口中查看记录的信息

  • 如果直接从Visual Studio运行项目,则可以在输出窗口中查看记录的信息。从输出窗口的下拉列表中选择ASP.NET Core Web Server。

  • 您将看到,信息按以下顺序记录

    • MW1:传入请求

    • MW2:传入请求

    • MW3:处理请求并生成响应

    • MW2:传出响应

    • MW1:传出响应

现在将上面的输出与微软的官方文档中的下图集合起来,是不是就清晰明了啊。吐槽下,微软的文档有粗糙。

640?wx_fmt=other

image.png

  • 请记住,asp.net Core中的中间件可以访问传入请求和传出响应

  • 请求先到达Middleware1,它记录(MW1:传入请求),因此我们首先看到此消息。

  • 然后Middleware1调用next()next()会调用管道中的Middleware2

  • Middleware2 记录(MW2:传入请求)

  • 然后 Middleware2 会调用next()再调用 Middleware3.

  • Middleware3处理请求并生成响应。因此,我们看到的下一条消息是(MW3:处理请求并生成响应)

  • 此时管道开始逆转。

  • 此时控制权将,交回到Middleware2,并将Middleware3生成的响应传递给它。Middleware2记录(MW2:传出响应),这是我们接下来看到的。

  • 最后, Middleware2将控制权交给 Midleware1

  • Middleware1 记录 (MW1: 传出响应), 这是我们最后看到的。

请求处理管道的中3个非常重要的知识点:

640?wx_fmt=png

  • 所有的请求都会在每个中间件组件调用next()方法之前触发。请求按照图中箭头的所示方向,依次穿过所有管道。

  • 当中间件处理请求并产生响应时,请求处理流程在管道中开始反向传递。

  • 所有的响应都会在每个中间件组件调用next()方法之前触发。响应按照图中箭头的所示方向,依次穿过所有管道。

小结


乱码问题

                context.Response.ContentType = "text/plain; charset=utf-8";


硬广专区



如果您觉得我的文章质量还不错,欢迎打赏,也可以订阅我的视频哦

未得到授权不得擅自转载本文内容,52abp.com保留版权

文字版目录: https://www.52abp.com/Wiki/mvc/latest/1.Intro 

交流QQ群:952387474《微软MVP带你学ASP.NET CORE》

【收费】腾讯课堂: https://ke.qq.com/course/392589?tuin=2522cdf3 
【免费】youtube视频专区:http://t.cn/Ei0F2EB 
免费的更新慢,收费的更新快,仅此而已。就这样。
 

640?wx_fmt=png

640?wx_fmt=jpeg

「好看」的人都【在看】↓↓↓



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值