先看下ASP.NET Core的启动代码,如下图:

通过以上代码,我们可以初步得出以下结论:

  • 所有的ASP.NET Core程序本质上也是一个控制台程序,使用Program的Main方法作为程序的入口。
  • 控制台Main入口-->IWebHostBuilder-->IWebHost-->Run,发现本质上就是启动一个作为宿主的Host。
  • 下面结合源码代详细分析下。

    宿主构造器:IWebHostBuilder

    看下WebHost的静态方法CreateDefaultBuilder的源码。

    /// <summary>
    /// Initializes a new instance of the <see cref="WebHostBuilder"/> class with pre-configured defaults.
    /// </summary>
    /// <remarks>
    /// The following defaults are applied to the returned <see cref="WebHostBuilder"/>:
    /// use Kestrel as the web server and configure it using the application's configuration providers,
    /// set the <see cref="IHostingEnvironment.ContentRootPath"/> to the result of <see cref="Directory.GetCurrentDirectory()"/>,
    /// load <see cref="IConfiguration"/> from 'appsettings.json' and 'appsettings.[<see cref="IHostingEnvironment.EnvironmentName"/>].json',
    /// load <see cref="IConfiguration"/> from User Secrets when <see cref="IHostingEnvironment.EnvironmentName"/> is 'Development' using the entry assembly,
    /// load <see cref="IConfiguration"/> from environment variables,
    /// load <see cref="IConfiguration"/> from supplied command line args,
    /// configure the <see cref="ILoggerFactory"/> to log to the console and debug output,
    /// and enable IIS integration.
    /// </remarks>
    /// <param name="args">The command line args.</param>
    /// <returns>The initialized <see cref="IWebHostBuilder"/>.</returns>
    public static IWebHostBuilder CreateDefaultBuilder(string[] args)
    {
    var builder = new WebHostBuilder(); if (string.IsNullOrEmpty(builder.GetSetting(WebHostDefaults.ContentRootKey)))
    {
    builder.UseContentRoot(Directory.GetCurrentDirectory());
    }
    if (args != null)
    {
    builder.UseConfiguration(new ConfigurationBuilder().AddCommandLine(args).Build());
    } builder.UseKestrel((builderContext, options) =>
    {
    options.Configure(builderContext.Configuration.GetSection("Kestrel"));
    })
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
    var env = hostingContext.HostingEnvironment; config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true); if (env.IsDevelopment())
    {
    var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
    if (appAssembly != null)
    {
    config.AddUserSecrets(appAssembly, optional: true);
    }
    } config.AddEnvironmentVariables(); if (args != null)
    {
    config.AddCommandLine(args);
    }
    })
    .ConfigureLogging((hostingContext, logging) =>
    {
    logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
    logging.AddConsole();
    logging.AddDebug();
    logging.AddEventSourceLogger();
    })
    .ConfigureServices((hostingContext, services) =>
    {
    // Fallback
    services.PostConfigure<HostFilteringOptions>(options =>
    {
    if (options.AllowedHosts == null || options.AllowedHosts.Count == 0)
    {
    // "AllowedHosts": "localhost;127.0.0.1;[::1]"
    var hosts = hostingContext.Configuration["AllowedHosts"]?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
    // Fall back to "*" to disable.
    options.AllowedHosts = (hosts?.Length > 0 ? hosts : new[] { "*" });
    }
    });
    // Change notification
    services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(
    new ConfigurationChangeTokenSource<HostFilteringOptions>(hostingContext.Configuration)); services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
    })
    .UseIIS()
    .UseIISIntegration()
    .UseDefaultServiceProvider((context, options) =>
    {
    options.ValidateScopes = context.HostingEnvironment.IsDevelopment();
    }); return builder;
    }

    1,UseContentRoot

    指定Web host使用的内容根目录,比如Views。默认为当前应用程序根目录。

    2,UseConfiguration

    //todo

    3,UseKestrel

    使用Kestrel作为默认的Web Server。

    4,ConfigureAppConfiguration

    设置当前应用程序配置。主要是读取 appsettings.json配置文件、开发环境中配置的UserSecrets、添加环境变量和命令行参数 。

    5,ConfigureLogging

    读取配置文件中的Logging节点,配置日志系统。

    6,ConfigureServices

    //todo

    7,UseIIS

    使用IIS中间件。

    8,UseIISIntegration

    使用IISIntegration中间件。

    9,UseDefaultServiceProvider

    设置默认的依赖注入容器。

    宿主:IWebHost

    在ASP.Net Core中定义了IWebHost用来表示Web应用的宿主,并提供了一个默认实现WebHost。宿主的创建是通过调用IWebHostBuilder的Build()方法来完成的。看下源码:

    /// <summary>
    /// Builds the required services and an <see cref="IWebHost"/> which hosts a web application.
    /// </summary>
    public IWebHost Build()
    {
    if (_webHostBuilt)
    {
    throw new InvalidOperationException(Resources.WebHostBuilder_SingleInstance);
    }
    _webHostBuilt = true; var hostingServices = BuildCommonServices(out var hostingStartupErrors);
    var applicationServices = hostingServices.Clone();
    var hostingServiceProvider = GetProviderFromFactory(hostingServices); if (!_options.SuppressStatusMessages)
    {
    // Warn about deprecated environment variables
    if (Environment.GetEnvironmentVariable("Hosting:Environment") != null)
    {
    Console.WriteLine("The environment variable 'Hosting:Environment' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
    } if (Environment.GetEnvironmentVariable("ASPNET_ENV") != null)
    {
    Console.WriteLine("The environment variable 'ASPNET_ENV' is obsolete and has been replaced with 'ASPNETCORE_ENVIRONMENT'");
    } if (Environment.GetEnvironmentVariable("ASPNETCORE_SERVER.URLS") != null)
    {
    Console.WriteLine("The environment variable 'ASPNETCORE_SERVER.URLS' is obsolete and has been replaced with 'ASPNETCORE_URLS'");
    }
    } AddApplicationServices(applicationServices, hostingServiceProvider); var host = new WebHost(
    applicationServices,
    hostingServiceProvider,
    _options,
    _config,
    hostingStartupErrors);
    try
    {
    host.Initialize(); var logger = host.Services.GetRequiredService<ILogger<WebHost>>(); // Warn about duplicate HostingStartupAssemblies
    foreach (var assemblyName in _options.GetFinalHostingStartupAssemblies().GroupBy(a => a, StringComparer.OrdinalIgnoreCase).Where(g => g.Count() > 1))
    {
    logger.LogWarning($"The assembly {assemblyName} was specified multiple times. Hosting startup assemblies should only be specified once.");
    } return host;
    }
    catch
    {
    // Dispose the host if there's a failure to initialize, this should clean up
    // will dispose services that were constructed until the exception was thrown
    host.Dispose();
    throw;
    } IServiceProvider GetProviderFromFactory(IServiceCollection collection)
    {
    var provider = collection.BuildServiceProvider();
    var factory = provider.GetService<IServiceProviderFactory<IServiceCollection>>(); if (factory != null && !(factory is DefaultServiceProviderFactory))
    {
    using (provider)
    {
    return factory.CreateServiceProvider(factory.CreateBuilder(collection));
    }
    } return provider;
    }
    }

    启动类:Startup

    每个ASP.NET Core程序都需要一个启动类,约定命名为:Startup。Startup用于配置服务和配置HTTP请求管道。

    namespace HelloNETCoreWebApi
    {
    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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    }
    else
    {
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
    } app.UseHttpsRedirection();
    app.UseMvc();
    }
    }
    }

    Startup必须包含Configure方法, 并选择包含ConfigureServices方法,这两个方法在应用程序启动时调用,该类还可以包含这些方法的特定环境的版本,并且ConfigureServices方法(如果存在)在Configure方法之前调用。

    Configure方法主要是配置ASP.NET Core的中间件,相当于我们在ASP.NET中所说的管道,ConfigureServices方法主要是配置依赖注入(DI)。

    ASP.NET Core基础1:应用启动流程的更多相关文章

    1. asp.net core mvc剖析:启动流程

      asp.net core mvc是微软开源的跨平台的mvc框架,首先它跟原有的MVC相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如taghelper,viewcomponent,D ...

    2. ASP.NET Core Razor 视图起始页 - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core Razor 视图起始页 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core Razor 视图起始页 上一章节中我们介绍了布局视图, ...

    3. 通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的?

      在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下来我们需要了解的是这样一个管道是如何被构建起来的.总的来说,管道由一个服务器和一个HttpApplication构成 ...

    4. net core mvc剖析:启动流程

      net core mvc剖析:启动流程 asp.net core mvc是微软开源的跨平台的mvc框架,首先它跟原有的MVC相比,最大的不同就是跨平台,然后又增加了一些非常实用的新功能,比如taghe ...

    5. ASP.NET Core 动作结果 - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 动作结果 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 动作结果 前面的章节中,我们一直使用简单的 C# 类作为控制器. 虽 ...

    6. ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 配置 MVC - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 配置 MVC 前面几章节中,我们都是基于 ASP.NET 空项目 ...

    7. ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 中间件 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 中间件 上一章节中,我们我们有讲到 Startup 类中的 Confi ...

    8. ASP.NET Core 项目配置 ( Startup ) - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 项目配置 ( Startup ) - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 项目配置 ( Startup ) 前面几章节 ...

    9. ASP.NET Core 基本项目目录结构 - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 基本项目目录结构 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 基本项目目录结构 上一章节中我们成功创建了一个名为 Hell ...

    10. ASP.NET Core 新建项目 - macOS 环境 - ASP.NET Core 基础教程 - 简单教程,简单编程

      原文:ASP.NET Core 新建项目 - macOS 环境 - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 新建项目 - macOS 环境 对于任何语言和 ...

    随机推荐

    1. C#线程的使用(1)

      今天刚开始学习使用线程,把学习过程与新的记录下来. 创建线程: 非常简单,只需声明她并为其提供线程起始点处的方法委托即可: 终止线程: 使用Abort和Join方法来实现: Abort方法:用于永久的 ...

    2. SDL 开发实战(四): SDL 事件处理

      在前面学习SDL的例子运行时,我们发现我们的窗口只停留了几秒,但是如果设置更长时间显然也有其他的弊端. 那么有没有一种好的办法可以解决这个问题呢?例如:能不能让窗口一直显示,直到检测到用户用鼠标点击关 ...

    3. [Swift]LeetCode678. 有效的括号字符串 | Valid Parenthesis String

      Given a string containing only three types of characters: '(', ')' and '*', write a function to chec ...

    4. AI - TensorFlow - 起步(Start)

      01 - 基本的神经网络结构 输入端--->神经网络(黑盒)--->输出端 输入层:负责接收信息 隐藏层:对输入信息的加工处理 输出层:计算机对这个输入信息的认知 每一层点开都有它相应的内 ...

    5. Python的数据库操作(pymysql)

      使用原生SQL语句进行对数据库操作,可完成数据库表的建立和删除,及数据表内容的增删改查操作等.其可操作性很强,如可以直接使用“show databases”.“show tables”等语句进行表格之 ...

    6. 受到 1 万点暴击,二狗子被 DDoS 攻击的惨痛经历

      二狗子的遭遇 “好消息,好消息,免费 DDoS 攻击软件上线了,性感黑客在线攻击,帮您攻克所有商业难题.”二狗子不知道在看着什么网站,新买的 Mac 中发出热闹的声音. 二狗子想知道“DDoS 是什么 ...

    7. web Components 学习之路

      就目前而言,纯粹的Web Components在兼容性方面还有着较为长远的路,这里做个记录总结,以纪念自己最近关于Web Components的学习道路. 参考教材 JavaScript 标准参考教程 ...

    8. Linux系统打开文件最大数量限制(进程打开的最大文件句柄数设置)

      ulimit  [-HSTabcdefilmnpqrstuvx  [limit]] 利用ulimit命令可以对资源的可用性进行控制. -H选项和-S选项分别表示对给定资源的硬限制(hard limit ...

    9. Too many authentication failures for xxxx_username

      解释 这个报错通常是因为多个ssh key 验证,key太多了导致服务器拒绝接受认证请求. 可以通过 -v 参数,输出详细的过程.你会发现你提供的认证key,服务器拒绝链接,并提示异常:"T ...

    10. Zookeeper~Linux环境下的部署

      介绍 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的软件,提 ...