一、概述

  在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载。Web应用程序的入口点由InetMgr.exe创建并调用托管,初始化过程中触发HttpApplication.Application_Start()事件。开发人员第一次执行代码的机会是处理Application_StartGlobal.asax中的事件。在ASP.NET Core中,Global.asax文件不再可用,已被新的初始化过程替代。

  

二、宿主

  ASP.NET Core应用程序其本质上是一个独立的控制台应用,是在.NET Core 控制台程序下调用特定的库,它并不是必需在 IIS内部托管且并不需要IIS来启动运行(而这正是ASP.NET Core跨平台的基石)。ASP.NET Core应用程序拥有一个内置的 Self-Hosted(自托管)的Web Server(Kestrel服务器),用来处理外部请求。 不管是托管还是自托管,都离不开Host(宿主)。在ASP.NET Core应用中通过配置并启动一个Host来完成应用程序的启动和其生命周期的管理。 而Host的主要的职责就是Web Server的配置和Pilpeline(请求处理管道)的构建。

  既然提到了宿主,下面就详细解释一下:

什么是宿主?

  ASP.NET Core应用程序需要在宿主中执行,一个宿主必须实现 IWebHost接口,该接口暴露了功能和服务的集合,以及一个 Start方法。宿主通常使用 WebHostBuilder的实例来创建,该实例构建并返回一个 WebHost实例。 WebHost引用一个将用于处理请求的服务器Kestrel。

宿主和服务器有什么不同?

  宿主负责应用程序启动和生命周期的管理。服务器Kestrel负责接受HTTP请求。宿主的部分职责还包括确保应用程序服务和服务器Kestrel可用并正确配置。你可以把宿主看作是服务器Kestrel的包装。宿主引用了Kestrel服务器接收HTTP请求;服务器并不知道它的宿主。

  所有的ASP.NET托管库都是从Program开始执行,而不是由IIS托管。

public class Program
    {    /// 创建宿主的步骤    /// ASP.NET Core应用程序的启动主要包含三个步骤:    /// CreateDefaultBuilder():创建IWebHostBuilder    /// Build():IWebHostBuilder负责创建IWebHost    /// Run():启动IWebHost
        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();// 调用Startup.cs类下的Configure 和 ConfigureServices
    }

以上是Program类中Main方法的示例代码,Main方法负责初始化Host宿主,调用Startup和执行应用程序。宿主将调用Startup类下面的ConfigureConfigureServices方法。

三、WebHostBuild

  WebHostBuild 用来构建 WebHost ,也是我们最先接触的一个类,它提供了如下方法:

  1、ConfigureAppConfiguration

  Configuration 在 ASP.NET Core 进行了全新的设计,使其更加灵活简洁,可以支持多种数据源。在 ASP.NET Core 1.x 中,我们是在Startup的构造函数中配置各种数据源的,而在 ASP.NET Core 2.0 中则移动了到Program中,这样能与控制台应用程序保持一致:

public static class WebHostBuilderExtensions
{
    public static IWebHostBuilder ConfigureAppConfiguration(this IWebHostBuilder hostBuilder, Action<IConfigurationBuilder> configureDelegate)
    {
        return hostBuilder.ConfigureAppConfiguration((context, builder) => configureDelegate(builder));
    }
}

public class WebHostBuilder : IWebHostBuilder
{
    private List<Action<WebHostBuilderContext, IConfigurationBuilder>> _configureAppConfigurationBuilderDelegates;
    public IWebHostBuilder ConfigureAppConfiguration(Action<WebHostBuilderContext, IConfigurationBuilder> configureDelegate)
    {
        if (configureDelegate == null)
        {
            throw new ArgumentNullException(nameof(configureDelegate));
        }

        _configureAppConfigurationBuilderDelegates.Add(configureDelegate);
        return this;
    }
}

_configureAppConfigurationBuilderDelegates委托会在 WebHostBuilder 的Build方法中执行,生成 IConfiguration 对象并以单例的形式注册到 DI 系统中, 我们可以在Startup以及应用程序的任何地方,通过 DI 系统来获取到。在CreateDefaultBuilder中会通过该方法来添加appsettinggs.json等基本配置的配置源

   2、UseSetting

  UseSetting 是一个非常重要的方法,它用来配置 WebHost 中的 IConfiguration 对象。需要注意与上面ConfigureAppConfiguration的区别, WebHost 中的 Configuration 只限于在 WebHost 使用,并且我们不能配置它的数据源,它只会读取ASPNETCORE_开头的环境变量:

private IConfiguration _config;

public WebHostBuilder()
{
    _config = new ConfigurationBuilder()
        .AddEnvironmentVariables(prefix: "ASPNETCORE_")
        .Build();
}

而我们比较熟悉的当前执行环境,也是通过该_config来读取的,虽然我们不能配置它的数据源,但是它为我们提供了一个UseSetting方法,为我们提供了一个设置_config的机会:

public string GetSetting(string key)
{
    return _config[key];
}

而我们通过UseSetting设置的变量最终也会以MemoryConfigurationProvider的形式添加到上面介绍的ConfigureAppConfiguration所配置的IConfiguration对象中。

  3、UseStartup

  UseStartup 这个我们都比较熟悉,它用来显式注册我们的Startup类,可以使用泛性,Type , 和程序集名称三种方式来注册:

// 常用的方法
public static IWebHostBuilder UseStartup<TStartup>(this IWebHostBuilder hostBuilder) where TStartup : class
{
    return hostBuilder.UseStartup(typeof(TStartup));
}

// 通过指定的程序集来注册 Startup 类
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, string startupAssemblyName)
{
    if (startupAssemblyName == null)
    {
        throw new ArgumentNullException(nameof(startupAssemblyName));
    }

    return hostBuilder
        .UseSetting(WebHostDefaults.ApplicationKey, startupAssemblyName)
        .UseSetting(WebHostDefaults.StartupAssemblyKey, startupAssemblyName);
}

// 最终的 Startup 类注册方法,上面两种只是一种简写形式
public static IWebHostBuilder UseStartup(this IWebHostBuilder hostBuilder, Type startupType)
{
    ....
}

  4、ConfigureLogging

  ConfigureLogging 用来配置日志系统,在 ASP.NET Core 1.x 中是在Startup类的Configure方法中,通过ILoggerFactory扩展来注册的,在 ASP.NET Core 中也变得更加简洁,并且统一通过 WebHostBuild 来配置:

public static class WebHostBuilderExtensions
{
    public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<ILoggingBuilder> configureLogging)
    {
        return hostBuilder.ConfigureServices(collection => collection.AddLogging(configureLogging));
    }

    public static IWebHostBuilder ConfigureLogging(this IWebHostBuilder hostBuilder, Action<WebHostBuilderContext, ILoggingBuilder> configureLogging)
    {
        return hostBuilder.ConfigureServices((context, collection) => collection.AddLogging(builder => configureLogging(context, builder)));
    }
}

AddLogging 是Microsoft.Extensions.Logging提供的扩展方法。

四、 Starup文件配置

  对于一个ASP.NET Core 程序而言,Startup 类是必须的。ASP.NET Core在程序启动时会从Program类中开始执行,然后再找到UseStartup<Startup>中找到配置的Startup的类,如果不指定Startup类会导致启动失败。

  在Startup中必须定义Configure方法,而ConfigureServices方法则是可选的,方法会在程序第一次启动时被调用,类似传统的ASP.NET MVC的路由和应用程序状态均可在Startup中配置,也可以在此初始化所需中间件。

Configure

  在ASP.NET Core 应用程序中Configure方法用于指定中间件以什么样的形式响应HTTP请求。 Configure 方法是用来配置请求管道的,通常会在这里会注册一些中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();//中间件:允许应用程序提供静态资源
            app.UseCookiePolicy();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });//中间件:将MVC添加到管道并允许配置路由
        }

  ASP.NET Core是通过对IApplicationBuilder进行扩展来构建中间件的, 上面代码中每个use扩展方法都是将中间件添加到请求管道。也可以给Configure方法附加服务(如:IHostingEnvironment)这些服务在ConfigureServices方法中被初始化。

用ASP.NET Core项目模板添加的应用程序,默认添加的几个中间件:

  • UseStaticFiles 允许应用程序提供静态资源。

  • UseMvc 将MVC添加到管道并允许配置路由。

ConfigureServices

  ConfigureServices方法是应用程序运行时将服务添加到容器中,用ASP.NET Core项目模板的时候默认会将MVC的服务添加到容器中。

public void ConfigureServices(IServiceCollection services){
    services.AddMvc();
}

五、处理管道(中间件)

  在ASP.NET Core应用程序中使用中间件,应用程序所做的任何事情(包括服务器中的静态文件)都是由中间件来完成的。没有任何中间件的应用程序在请求的出错时候简单返回404 Not Found。中间件可以让您完全控制请求的处理方式,并且让您的应用程序更加精简。

当接收到一个请求时,请求会交给中间件构成的中间件管道进行处理,管道就是多个中间件构成,请求从一个中间件的一端进入,从中间件的另一端出来,每个中间件都可以对HttpContext请求开始和结束进行处理:

参考

运行原理:https://blog.csdn.net/sD7O95O/article/details/78126384

宿主介绍:http://www.jkeabc.com/460935.html

WebHostBuild:https://blog.csdn.net/linux12a/article/details/77676127

中间件:https://www.cnblogs.com/vipyoumay/p/5640645.html

中间件请求管道的构成:https://blog.csdn.net/bieguolaia/article/details/77816445

.NET CORE学习笔记系列(5)——ASP.NET CORE的运行原理解析的更多相关文章

  1. .NET CORE学习笔记系列(4)——ASP.NET CORE 程序启用SSL

    一.什么是SSL? 1.概念: SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数 ...

  2. .NET CORE学习笔记系列(3)——ASP.NET CORE多环境标识

    在开发项目的过程当中,生产环境与调试环境的配置是不一样的.比如连接字符串. ASP .NET CORE 支持利用环境变量来动态配置 JSON 文件.ASP.NET Core 引用了一个特定的环境变量  ...

  3. .NET CORE学习笔记系列(1)——ASP.NET MVC Core 介绍和项目解读

    ASP.NET MVC Core 项目文件夹解读 一.项目文件夹总览 1.1.Properties——launchSettings.json 启动配置文件,你可以在项目中“Properties”文件夹 ...

  4. ASP.NET Core 学习笔记 第一篇 ASP.NET Core初探

    前言 因为工作原因博客断断续续更新,其实在很早以前就有想法做一套关于ASP.NET CORE整体学习度路线,整体来说国内的环境的.NET生态环境还是相对比较严峻的,但是干一行爱一行,还是希望更多人加入 ...

  5. .NET CORE学习笔记系列(2)——依赖注入[6]: .NET Core DI框架[编程体验]

    原文https://www.cnblogs.com/artech/p/net-core-di-06.html 毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动 ...

  6. .NET CORE学习笔记系列(2)——依赖注入【3】依赖注入模式

    原文:https://www.cnblogs.com/artech/p/net-core-di-03.html IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架中以实现对流 ...

  7. .NET CORE学习笔记系列(2)——依赖注入【1】控制反转IOC

    原文:https://www.cnblogs.com/artech/p/net-core-di-01.html 一.流程控制的反转 IoC的全名Inverse of Control,翻译成中文就是“控 ...

  8. 学习ASP.NET Core Razor 编程系列五——Asp.Net Core Razor新建模板页面

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

  9. .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]

    原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...

随机推荐

  1. asp.net core系列 37 WebAPI 使用OpenAPI (swagger)中间件

    一.概述 在使用Web API时,对于开发人员来说,了解其各种方法可能是一项挑战.在ASP.NET Core上,Web api 辅助工具介绍二个中间件,包括:Swashbuckle和NSwag .NE ...

  2. Python爬虫入门教程 28-100 虎嗅网文章数据抓取 pyspider

    1. 虎嗅网文章数据----写在前面 今天继续使用pyspider爬取数据,很不幸,虎嗅资讯网被我选中了,网址为 https://www.huxiu.com/ 爬的就是它的资讯频道,本文章仅供学习交流 ...

  3. C#版(击败97.76%的提交) - Leetcode 557. 反转字符串中的单词 III - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. Leetcod ...

  4. 【链表问题】打卡2:删除单链表的第 K个节点

    前言 以专题的形式更新刷题贴,欢迎跟我一起学习刷题.每道题会提供简单的解答. 题目描述 在单链表中删除倒数第 K 个节点 要求 如果链表的长度为 N, 时间复杂度达到 O(N), 额外空间复杂度达到 ...

  5. 【WCF学习大全】

    我的WCF之旅(1):创建一个简单的WCF程序 我的WCF之旅(2):Endpoint Overview 我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communica ...

  6. SmartSql = Dapper + MyBatis + Cache(Memory | Redis) + ZooKeeper + R/W Splitting + ......

    SmartSql Why 拥抱 跨平台 DotNet Core,是时候了. 高性能.高生产力,超轻量级的ORM.156kb (Dapper:168kb) So SmartSql TargetFrame ...

  7. sysbench的框架实现介绍

    sysbench是一个非常经典的综合性能测试工具,它支持CPU,IO,内存,尤其是数据库的性能测试.那它是怎么做到通用性的呢,总结一句话是大量运用了重载的方法. sysbench总体架构 sysben ...

  8. ASP.NET Core 2.1 : 十三.httpClient.GetAsync 报SSL错误的问题

    不知什么时候 ,出现了这样的一个奇怪问题,简单的httpClient.GetAsync("xxxx")居然报错了.(ASP.NET Core 系列目录) 一.问题描述 把原来的程序 ...

  9. [零]java8 函数式编程入门官方文档中文版 java.util.stream 中文版 流处理的相关概念

    前言 本文为java.util.stream 包文档的译文 极其个别部分可能为了更好理解,陈述略有改动,与原文几乎一致 原文可参考在线API文档 https://docs.oracle.com/jav ...

  10. java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类

    本文关键词: java集合框架  框架设计理念  容器 继承层级结构 继承图 集合框架中的抽象类  主要的实现类 实现类特性   集合框架分类 集合框架并发包 并发实现类 什么是容器? 由一个或多个确 ...