ASP.NET Core 核心特性--宿主、启动、中间件
宿主
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
CreateDefaultBuilder 创建 IHostBuilder 对象时所包含的主要默认选项包括:
- 配置 Kestrel 服务器作为默认的 Web 服务器来负责处理 Web 的请求与响应
- 使用当前目录作为应用程序的内容目录(ContentRoot),该目录决定了 ASP.NET Core 查找内容文件(如 MVC 视图等)的位置
- 从以 ASPNETCORE_ 开头的环境变量(如 ASPNETCORE_ENVIRONMENT)中以及命令行参数中加载配置项
- 从 appsettings.json、appsettings.{Environment}.json、用户机密(仅开发环境)、环境变量和命令行参数等位置加载应用设置
- 配置日志功能,默认添加控制台输出和调式输出
- 如果应用程序被托管在 IIS 中,启动 IIS 集成,它会配置应用程序的主机地址和端口,并允许捕获启动错误等
启动
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
- ConfigureServices 用于向 ASP.NET Core 的依赖注入容器添加服务
- Configure 用于添加中间件,配置请求管道
这两个方法都会在运行时被调用,且在应用程序的整个生命周期内,只执行一次。其中 ConfigureServices 方法是可选的,而 Configure 方法则是必须的。在程序启动时,它会执行 ConfigureServices 方法(如果有),将指定的服务放入应用程序的依赖注入容器中,然后再执行 Configure 方法,向请求管道中添加中间件。
中间件
所谓中间件,就是处理 HTTP 请求和响应的组件,它本质上是一段用来处理请求与响应的代码。多个中间件之间的链式关系使之形成了管道(Pipeline)或者请求管道。管道意味着请求将从一端进入,并按照一定的顺序由每一个中间件处理,最后由另一端出来。
添加中间件:
Run & Use
// Use 方法在处理完成后还会将请求传入下一个中间件,并由它继续处理
app.Use(async (context, next) =>
{
Console.WriteLine("中间件 A:开始");
await next();// 下一个中间件
Console.WriteLine("中间件 A:结束");
});
app.Run(async (context) =>
{
Console.WriteLine("中间件 B");
await context.Response.WriteAsync("Hello, world");
});
启动程序,输出如下:
中间件 A:开始
中间件 B
中间件 A:结束
Map
app.Use(async (context, next) =>
{
Console.WriteLine("中间件 A:开始");
await next();// 下一个中间件
Console.WriteLine("中间件 A:结束");
});
// 根据是否配置指定的请求路径来决定是否在一个新分支上继续执行后续的中间件
// 并且在新分支上执行完后,不再回到原来的管道上
app.Map(new PathString("/maptest"),
a => a.Use(async (context, next) =>
{
Console.WriteLine("中间件 B:开始");
await next(); // 下一个中间件
Console.WriteLine("中间件 B:结束");
}));
app.Run(async context =>
{
Console.WriteLine("中间件 C");
await context.Response.WriteAsync("Hello, world");
});
访问 https://localhost:5001/maptest
中间件 A:开始
中间件 B:开始
中间件 B:结束
中间件 A:结束
UseWhen
// Use 方法在处理完成后还会将请求传入下一个中间件,并由它继续处理
app.Use(async (context, next) =>
{
Console.WriteLine("中间件 A:开始");
await next();// 下一个中间件
Console.WriteLine("中间件 A:结束");
});
// 所有添加的中间件都会执行
app.UseWhen(context => context.Request.Path.Value == "/maptest",
a => a.Use(async (context, next) =>
{
Console.WriteLine("中间件 B:开始");
await next(); // 下一个中间件
Console.WriteLine("中间件 B:结束");
}));
app.Run(async context =>
{
Console.WriteLine("中间件 C");
await context.Response.WriteAsync("Hello, world");
});
访问 https://localhost:5001/maptest
中间件 A:开始
中间件 B:开始
中间件 C
中间件 B:结束
中间件 A:结束
自定义中间件
public class HttpMethodCheckMiddleware
{
// 在管道中的下一个中间件
private readonly RequestDelegate _next;
/// <summary>
/// 构造函数中可以得到下一个中间件,并且还可以注入需要的服务,比如 IHostEnvironment
/// </summary>
/// <param name="requestDelegate"></param>
/// <param name="environment"></param>
public HttpMethodCheckMiddleware(RequestDelegate requestDelegate, IHostEnvironment environment)
{
this._next = requestDelegate;
}
/// <summary>
/// 对 HTTP 请求方法进行判断,如果符合条件则继续执行下一个中间件
/// 否则返回 400 Bad Request 错误,并在响应中添加自定义消息头用于说明错误原因
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public Task Invoke(HttpContext context)
{
var requestMethod = context.Request.Method.ToUpper();
if (requestMethod == HttpMethods.Get || requestMethod == HttpMethods.Head)
{
return _next(context);
}
else
{
context.Response.StatusCode = 400;
context.Response.Headers.Add("X-AllowHTTPWeb", new[] {"GET,HEAD"});
context.Response.WriteAsync("只支持 GET、HEAD 方法");
return Task.CompletedTask;
}
}
}
添加自定义中间件
app.UseMiddleware<HttpMethodCheckMiddleware>();
创建扩展方法
public static class CustomMiddlewareExtensions
{
public static IApplicationBuilder UseHttpMethodCheckMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HttpMethodCheckMiddleware>();
}
}
调用扩展方法添加中间件
app.UseHttpMethodCheckMiddleware();
参考资料
《ASP.ENT Core 与 RESTful API 开发实战》
如果阅读文章后有所收获,希望您可以点一个推荐,感觉不尽!!!

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。
如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。
ASP.NET Core 核心特性--宿主、启动、中间件的更多相关文章
- Asp.Net Core 第06局:中间件
总目录 前言 本文介绍Asp.Net Core 中间件. 环境 1.Visual Studio 2017 2.Asp.Net Core 2.2 开局 第一手:中间件概述 1.中间件:添加到应用 ...
- ASP.NET Core管道详解[6]: ASP.NET Core应用是如何启动的?[下篇]
要承载一个ASP.NET Core应用,只需要将GenericWebHostService服务注册到承载系统中即可.但GenericWebHostService服务具有针对其他一系列服务的依赖,所以在 ...
- asp.net core 核心对象解析
首先声明这篇文章的所有内容均来自https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html ----感谢大内老A(artec ...
- Asp.Net Core 3.1 的启动过程5
前言 本文主要讲的是Asp.Net Core的启动过程,帮助大家掌握应用程序的关键配置点. 1.创建项目 1.1.用Visual Studio 2019 创建WebApi项目. 这里面可以看到有两个关 ...
- ASP.NET Core 中的那些认证中间件及一些重要知识点
前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...
- [转]ASP.NET Core 中的那些认证中间件及一些重要知识点
本文转自:http://www.qingruanit.net/c_all/article_6645.html 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系 ...
- asp.net core mvc剖析:启动流程
asp.net core mvc是微软开源的跨平台的mvc框架,首先它跟原有的MVC相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如taghelper,viewcomponent,D ...
- asp.net core 教程(六)-中间件
Asp.Net Core-中间件 在这一章,我们将了解如何设置中间件.中间件技术在 ASP.NET Core中控制我们的应用程序如何响应 HTTP 请求.它还可以控制应用程序的异常错误,这是一个在如何 ...
- Asp .Net core 2 学习笔记(2) —— 中间件
这个系列的初衷是便于自己总结与回顾,把笔记本上面的东西转移到这里,态度不由得谨慎许多,下面是我参考的资源: ASP.NET Core 中文文档目录 官方文档 记在这里的东西我会不断的完善丰满,对于文章 ...
随机推荐
- javascript中的function命名空間與模擬getter、setter
function的命名空間 在javascript中,function也可以擁有自己的命名空間例如以下這段程式碼: 12345678 function () { return 'I am A';} A ...
- 运输层协议TCP和UDP
运输层协议TCP和UDP 一.用户数据报协议 UDP 1.1.UDP 概述 UDP 只在 IP 的数据报服务之上增加了很少一点的功能,即端口的功能和差错检测的功能. 虽然 UDP 用户数据报只能提供不 ...
- SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」
有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...
- Failed to open the key database file. c;\\User\\w\\Destop\\SecureCRT_FX6.5.3\\Config\\KnowHosts\\Hostsmap.txt这个问题的解决方法
1.首先将这段错误在百度翻译上面查询一下,是什么意思,查询结果如下: 打开密钥数据库文件失败.C:\用户\ w \平台\ securecrt_fx6.5.3 \\ \\ \\ hostsmap.txt ...
- 通读Python官方文档之cgitb
cgitb CGI脚本异常管理 源代码:Lib/cgitb.py cgitb模块为Python脚本提供了一个特殊的异常管理器.名字有点误导人,它最初设计是为了以HTML格式展示cgi脚本的大量异常信息 ...
- dom节点及对节点的常用操作方法
dom节点及对节点的常用操作方法 在说dom节点前,先来看看页面的呈现: dom渲染流程: 1.浏览器解析html源码,然后创建一个DOM树. 在DOM树中,每一个HTML标签都有一个对应的节点(元 ...
- 基于SpringCloud搭建项目-Zuul篇(六)
本文主要介绍zuul的基本原理和在sprngcloud服务下如何使用 一.简单介绍 Zuul 是 Netflix OSS 中的一员,是一个基于 JVM 路由和服务端的负载均衡器.提供路由.监控.弹性. ...
- php -v 找不到命令
[root@localhost htdocs]# php -v -bash: php: command not found export PATH=$PATH:/usr/local/php7/bin ...
- aosp Pixel 修改 SIM 卡支持及解决网络带x问题
去除网络X的方法 adb shell settings put global captive_portal_https_url http://g.cn/generate_204 自己用 php 做一个 ...
- web实验二 ---通过jQuery实现用户注册身份验证
通过jQuery实现用户注册身份验证,当每个文本框失去焦点时进行该文本框内容校验,并将校验信息在文本框右侧显示出结果. 具体校验要求: 1.用户名由6-18位字符组成 2.密码由6-18位字符组成,且 ...