ASP.NET Core框架深度学习(一) Hello World
对于学习Core的框架,对我帮助最大的一篇文章是Artech的《200行代码,7个对象——让你了解ASP.NET Core框架的本质》,最近我又重新阅读了一遍该文。本系列文章就是结合我的阅读心得,一起来搭建一个迷你的Core框架。
本文相关代码在码云上,链接如下
https://gitee.com/qixinbo/MyKestrelServer/tree/master/CoreMini/CoreMini
还有部分是core的源码,链接如下
https://github.com/aspnet/AspNetCore/tree/master/src/Http
1、从Hello World谈起
当我们最开始学习一门技术的时候都喜欢从Hello World来时,貌似和我们本篇的主题不太搭。但事实却非如此,在我们看来如下这个Hello World是对ASP.NET Core框架本质最好的体现。
public class Program
{
public static void Main()
=> new WebHostBuilder()
.UseKestrel()
.Configure(app => app.Run(context => context.Response.WriteAsync("Hello World!")))
.Build()
.Run();
}
如上这个Hello World程序虽然人为地划分为若干行,但是整个应用程序其实只有一个语句。这个语句涉及到了ASP.NET Core程序两个核心对象WebHost和WebHostBuilder。我们可以将WebHost理解为寄宿或者承载Web应用的宿主,应用的启动可以通过启动作为宿主的WebHost来实现。至于WebHostBuilder,顾名思义,就是WebHost的构建者。
在调用WebHostBuilder的Build方法创建出WebHost之前,我们调用了它的两个方法,其中UseKestrel旨在注册一个名为Kestrel的服务器,而Configure方法的调用则是为了注册一个用来处理请求的中间件,后者在响应的主体内容中写入一个“Hello World”文本。
(Configure本质上是把一个委托加入到了中间件的集合中。)
UseKestrel代码
public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder)
{
//同样是ConfigureServices,跟平时我们startup里面进行注册是一样的
return hostBuilder.ConfigureServices(services =>
{
// Don't override an already-configured transport
services.TryAddSingleton<ITransportFactory, SocketTransportFactory>(); services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
services.AddSingleton<IServer, KestrelServer>();
});
}
当我们调用Run方法启动作为应用宿主的WebHost的时候,后者会利用WebHostBuilder提供的服务器和中间件构建一个请求处理管道。这个由一个服务器和若干中间件构成的管道就是ASP.NET Core框架的核心,我们接下来的核心任务就是让大家搞清楚这个管道是如何被构建起来的,以及该管道采用怎样的请求处理流程。

Servicer有StartAsync或者叫run的方法
run的代码
public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
} /// <summary>
/// Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task RunAsync(this IWebHost host, CancellationToken token = default)
{
// Wait for token shutdown if it can be canceled
if (token.CanBeCanceled)
{
await host.RunAsync(token, shutdownMessage: null);
return;
} // If token cannot be canceled, attach Ctrl+C and SIGTERM shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
var shutdownMessage = host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages ? string.Empty : "Application is shutting down...";
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: shutdownMessage); try
{
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
}
finally
{
done.Set();
}
}
}
private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
{
using (host)
{
await host.StartAsync(token);
var hostingEnvironment = host.Services.GetService<IHostingEnvironment>();
var options = host.Services.GetRequiredService<WebHostOptions>();
if (!options.SuppressStatusMessages)
{
Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (serverAddresses != null)
{
foreach (var address in serverAddresses)
{
Console.WriteLine($"Now listening on: {address}");
}
}
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
} await host.WaitForTokenShutdownAsync(token);
}
}
2、ASP.NET Core Mini
如何深入地去一个开发框架?有一个方法我倒很乐意与大家分享,那就是当你在学习一个开发框架的时候不要只关注编程层面的东西,而应该将更多的精力集中到对架构设计层面的学习。
针对某个框架来说,它提供的编程模式纷繁复杂,而底层的设计原理倒显得简单明了。那么如何检验我们对框架的设计原理是否透彻呢,我觉得最好的方式就是根据你的理解对框架进行“再造”。当你按照你的方式对框架进行“重建”的过程中,你会发现很多遗漏的东西。如果被你重建的框架能够支撑一个可以运行的Hello World应用,那么可以基本上证明你已经基本理解了这个框架最本质的东西。
虽然ASP.NET Core目前是一个开源的项目,我们可以完全通过源码来学习它,但是我相信这对于绝大部分人来说是有难度的。为此我们将ASP.NET Core最本质、最核心的部分提取出来,重新构建了一个迷你版的ASP.NET Core框架。

ASP.NET Core Mini具有如上所示的三大特点。第一、它是对真实ASP.NET Core框架的真实模拟,所以在部分API的定义上我们做了最大限度的简化,但是两者的本质是完全一致的。如果你能理解ASP.NET Core Mini,意味着你也就是理解了真实ASP.NET Core框架。第二、这个框架是可执行的,我们提供的并不是伪代码。第三、为了让大家能够在最短的时间内理解ASP.NET Core框架的精髓,ASP.NET Core Mini必需足够简单,所以我们整个实现的核心代码不会超过200行。
3、Hello World 2
既然我们的ASP.NET Core Mini是可执行的,意味着我们可以在上面构建我们自己的应用,如下所示的就是在ASP.NET Core Mini上面开发的Hello World,可以看出它采用了与真实ASP.NET Core框架一致的编程模式。
public class Program
{
public static async Task Main()
{
await new WebHostBuilder()
.UseHttpListener()
.Configure(app => app
.Use(FooMiddleware)
.Use(BarMiddleware)
.Use(BazMiddleware))
.Build()
.StartAsync();
}
public static RequestDelegate FooMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Foo=>");
await next(context);
};
public static RequestDelegate BarMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Bar=>");
await next(context);
};
public static RequestDelegate BazMiddleware(RequestDelegate next)
=> context => context.Response.WriteAsync("Baz");
}
我们有必要对上面这个Hello World程序作一个简答的介绍:在创建出WebHostBuilder之后,我们调用了它的扩展方法UseHttpListener注册了一个自定义的基于HttpListener的服务器,我们会在后续内容中介绍该服务器的实现。在随后针对Configure方法的调用中,我们注册了三个中间件。由于中间件最终是通过Delegate对象来体现的,所以我们可以将中间件定义成与Delegate类型具有相同签名的方法。
我们目前可以先不用考虑表示中间件的三个方法为什么需要成如上的形式,只需要知道三个中间件在针对请求的处理流程中都作了些什么。上面的代码很清楚,三个中间件分别会在响应的内容中写入一段文字,所以程序运行后,如果我们利用浏览器访问该应用,会得到如下所示的输出结果。

备注:这里UseHttpListener调用的命名空间是System.Net.HttpListener,是微软平台监听http请求的一个关键类库。
ASP.NET Core框架深度学习(一) Hello World的更多相关文章
- ASP.NET Core框架深度学习(四)宿主对象
11.WebHost 第六个对象 到目前为止我们已经知道了由一个服务器和多个中间件构成的管道是如何完整针对请求的监听.接收.处理和最终响应的,接下来来讨论这样的管道是如何被构建出来的.管道是在作为应 ...
- ASP.NET Core框架深度学习(二) 管道对象
4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...
- ASP.NET Core框架深度学习(三) Server对象
8.Server 第五个对象 服务器在管道中的职责非常明确,当我们启动应用宿主的WebHost的时候,服务它被自动启动.启动后的服务器会绑定到指定的端口进行请求监听,一旦有请求抵达,服务器会根据该 ...
- ASP.NET Core 框架本质学习
本文作为学习过程中的一个记录. 学习文章地址: https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 一. ASP.N ...
- ASP.NET Core Web开发学习笔记-1介绍篇
ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...
- 一个Mini的ASP.NET Core框架的实现
一.ASP.NET Core Mini 在2019年1月的微软技术(苏州)俱乐部成立大会上,蒋金楠老师(大内老A)分享了一个名为“ASP.NET Core框架揭秘”的课程,他用不到200行的代码实现了 ...
- 200行代码,7个对象——让你了解ASP.NET Core框架的本质
2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘>的分享.在此次分享中,我按照ASP.NET Core自身的运行原理和设计 ...
- 了解ASP.NET Core框架的本质
了解ASP.NET Core框架的本质 ASP.NET Core自身的运行原理和设计思想创建了一个 “迷你版” 的ASP.NET Core框架,并且利用这个 “极简” 的模拟框架阐述了ASP.NET ...
- 200行代码,7个对象——让你了解ASP.NET Core框架的本质
原文:200行代码,7个对象--让你了解ASP.NET Core框架的本质 2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘&g ...
随机推荐
- ArrayList和LinkedList介绍
java.util.ArrayList集合的数据存储结构是数组,且是多线程,元素增删慢,查找快, 由于日常使用开发大多数为查询数据,遍历数据,所以ArrayList是最常用的集合.上一节已写了. ja ...
- Django多数据库
每个app使用不同的数据库 1. 配置数据库连接 # settings.py # DATABASES中必须要有default字段 DATABASES = { 'default': { 'ENGINE' ...
- 使用Redis实现延时任务(二)
前提 前一篇文章通过Redis的有序集合Sorted Set和调度框架Quartz实例一版简单的延时任务,但是有两个相对重要的问题没有解决: 分片. 监控. 这篇文章的内容就是要完善这两个方面的功能. ...
- AttributeError: 'unicode' object has no attribute 'tzinfo' 未解决
Internal Server Error: /demo/machineinfo.htmlTraceback (most recent call last): File "C:\Python ...
- Dynamics CRM 2015/2016新特性之三十四:有了插件日志,调试插件so easy!
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复217或者20160330可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- 记录C#连接数据库工具类
一.SQL Server /// <summary> /// 数据库的通用访问代码 /// 此类为抽象类, /// 不允许实例化,在应用时直接调用即可 /// </summary&g ...
- bayaim_mysql5.6下table_open_cache参数
bayaim_mysql5.6下table_open_cache参数_2017年12月26日10:51:58 原创 作者:bayaim 时间:2017-12-26 10:57:17 1 0删除编辑 ( ...
- [20191101]完善vim的bccalc插件8.txt
[20191101]完善vim的bccalc插件8.txt --//今天移植bccalc插件到linux,发现一些问题.我自己已经在windows下使用一段时间,从来没有在linux下测试.看来很少人 ...
- ERROR: Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/itsdangerous' Consider using the `--user` option or check the permissions
近期练习flask写个blog, 安装flask扩展时 pip install Flask-WTF 报ERROR: Could not install packages due to an Envir ...
- linux 命令cp -a的用法
cp -a 保留原文件属性的前提下复制文件 cp -r dirname(源文件) destdi(目标文件) 复制目录后其文件属性会发生变化想要使得复制之后的目录和原目录完全一样包括文件权限,可以使用c ...