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

在本节中,我们将讨论使用中间件组件为 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()方法中的代码。

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()扩展方法,我们只能将一个终端中间件添加到请求管道。
  • 终端中间件是我们之前已经说到过,他会使管道短路,不会去调用下一个中间件。

研究下面的代码

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类型,即它是代表管道中下一个中间件的通用委托。

我们再看看以下代码

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:传出响应

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

  • 请记住,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 个非常重要的知识点:

  • 所有的请求都会在每个中间件组件调用next()方法之前触发。请求按照图中箭头的所示方向,依次穿过所有管道。
  • 当中间件处理请求并产生响应时,请求处理流程在管道中开始反向传递。
  • 所有的响应都会在每个中间件组件调用next()方法之前触发。响应按照图中箭头的所示方向,依次穿过所有管道。

小结

Response 为抽象类

乱码问题

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

欢迎添加个人微信号:Like若所思。

欢迎关注我的公众号,不仅为你推荐最新的博文,还有更多惊喜和资源在等着你!一起学习共同进步!

配置 ASP.NET Core 请求(Request)处理管道的更多相关文章

  1. ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Identity 配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Identity 配置 上一章节我们简单介绍了下 Id ...

  2. 深入探究ASP.NET Core读取Request.Body的正确方式

    前言 相信大家在使用ASP.NET Core进行开发的时候,肯定会涉及到读取Request.Body的场景,毕竟我们大部分的POST请求都是将数据存放到Http的Body当中.因为笔者日常开发所使用的 ...

  3. 本文演示如何配置ASP.NET Core项目以在Visual Studio(VS)2017中使用Telerik UI for ASP.NET Core。

    学习时使用的是VS2017+Core2.1了,不再讨论VS2015和core1.1的东西. 配置ASP.NET Core Web应用程序以使用Telerik UI for ASP.NET Core: ...

  4. 使用Enablebuffering多次读取Asp Net Core 请求体

    使用Enablebuffering多次读取Asp Net Core 请求体 1 .Net Core 2.X时代 使用EnableRewind倒带 public IActionResult Index( ...

  5. 用"hosting.json"配置ASP.NET Core站点的Hosting环境

    通常我们在 Prgram.cs 中使用硬编码的方式配置 ASP.NET Core 站点的 Hosting 环境,最常用的就是 .UseUrls() . public class Program { p ...

  6. 自动化CodeReview - ASP.NET Core请求参数验证

    自动化CodeReview系列目录 自动化CodeReview - ASP.NET Core依赖注入 自动化CodeReview - ASP.NET Core请求参数验证 参数验证实现 在做服务端开发 ...

  7. ASP.NET Core macOS 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core macOS 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 是对 ASP.NET 有重大意义的一次重新设计.本章节我 ...

  8. ASP.NET Core Windows 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core Windows 环境配置 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Windows 环境配置 ASP.NET Core ...

  9. ASP.NET Core 请求/查询/响应参数格式转换(下划线命名)

    业务场景: 在 ASP.NET Core 项目中,所有的代码都是骆驼命名,比如userName, UserName,但对于 WebApi 项目来说,因为业务需要,一些请求.查询和响应参数的格式需要转换 ...

随机推荐

  1. 用 Python 自动监测 GitHub 项目更新

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: GitPython PS:如有需要Python学习资料的小伙伴可以加 ...

  2. 易优CMS:volist的基础应用

      [基础用法] 名称:volist 功能:数据/记录循环输出标签 语法: {eyou:channel type='top'}            {eyou:volist name='$field ...

  3. 数据类型和特殊类型-C#

    参考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1.集合set:纯粹的数据集合 2.线性结构:一对一的,数组 3.树形结构: ...

  4. c# jetbrains rider使用一段时间后

    先上一个官方的对比图吧.https://www.jetbrains.com/rider/compare/rider-vs-visual-studio/index.html 功能上直接超越visual ...

  5. 【微信小程序】App.js生命周期

    1.小程序的生命周期-App.js App() 必须在 app.js 中注册,且不能注册多个.所以App()方法在一个小程序中有且仅有一个. App({ onLaunch: function () { ...

  6. 【JavaScript】JavaScript基础

    JavaScript简介 JavaScript历史 在上世纪1995年,著名的互联网公司网景公司希望能在静态HTML页面上添加一些动态效果,于是叫Brendan Eich这哥们在两周之内设计出了Jav ...

  7. [b0030] python 归纳 (十五)_多进程使用Pool

    1 usePool.py #coding: utf-8 """ 学习进程池使用 multiprocessing.Pool 总结: 1. Pool 池用于处理 多进程,并不 ...

  8. 如何把转入成功的XXX.sql导入到自己的数据库里

    1.新建自己的mysql连接,mysql连接名随便起,如cxf  密码尽量写123456或者root,防止忘记.按照图示右键(如果想在已有的mysql连接基础上建立数据库连接直接看第二步) 2.右键名 ...

  9. easyui三

    陈旧的开发模式 美工(ui工程师:出一个项目模型) java工程师:将原有的html转成jsp,动态展示数据 缺点: 客户需要调节前端的展示效果 解决:由美工去重新排版,重新选色.Vs前后端分离 美工 ...

  10. c# 第26节 Main方法

    本节内容: 1:Main方法 2:Main方法的定义 3:测试Main函数传入参数 4:Main的大总结 1:Main方法是什么 2:Main方法的定义 3:测试打印出外部传入Main的参数 clas ...