ASP.NET Core基礎1:應用啟動流程

来源:https://www.cnblogs.com/mcgrady/archive/2019/01/09/10243416.html
-Advertisement-
Play Games

先看下ASP.NET Core的啟動代碼,如下圖:通過以上代碼,我們可以初步得出以下結論:所有的ASP.NET Core程式本質上也是一個控制台程式,使用Program的Main方法作為程式的入口。控制台Main入口-->IWebHostBuilder-->IWebHost-->Run,發現本質上就... ...


先看下ASP.NET Core的啟動代碼,如下圖:


image

通過以上代碼,我們可以初步得出以下結論:

  • 所有的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)。


    您的分享是我們最大的動力!

    -Advertisement-
    Play Games
    更多相關文章
    • ...
    • 1.Convert類型轉換 總結: 類型如果相相容的兩個變數,可以使用自動類型轉換或者強制類型轉換。 但是,如果兩個類型的變數不相容,比如string與int或者string 與double, 這個時候我們可以使用一個叫做Convert的轉換工廠進行轉換。 註意:使用Convert進行類型轉換,也需 ...
    • 清晨起床,震驚了,窗外一片雪白,大雪紛飛,我承認我詞窮了,說再多話也描述不了此刻的大好心情。所以,話不多說,先上一張朋友圈的圖吧! 趁著這麼“好的”天氣以及這麼好的心情突然想寫點東西記錄一下自己的2018這一年以及2019年的這一天以及對.NET Core的看法。 俗話說“瑞雪兆豐年”,其實我想說這 ...
    • 第一種,自己手寫dockerfile發佈,上傳至hubDocker 1. 正常發佈到文件夾中,發佈文件上傳至linux機器上。如 /www/app 2. 將Dockerfile文件也複製到同目錄 。/www/app 3. 輸入 ,構建一個demo名字的鏡像。這個時候就會構建鏡像,輸入 可以查看當剛剛 ...
    • 之前都是看別人寫博客,自己沒有寫博客的習慣.在工作的過程中,總是會碰到許多的技術問題.有很多時候想記錄下來,後面一直有許多的問題等著解決.總想著等系統完成了,再回頭總結下.往往結果就把這事拋到腦後了. 總覺得不能一直這樣哈.今天簡單記一下吧.有表達不清楚的地方,多多包涵. 最近在研究.net orm ...
    • https://stackoverflow.com/questions/45875981/error while reading json file in dotnet core the configured user limit 128 on You are creating file watch ...
    • 在 .Net Core 2.2中 Microsoft.AspNetCore.App 預設內置了EntityFramework Core 包,所以在使用過程中,我們無需再從 NuGet 倉庫單獨應用 EFCore 包;本文並不打算深入的介紹 EFCore 的各種使用方式、原理解析,本文重點在於解決讓初... ...
    • 解決方法 定位到csproject 文件夾 問題解決 接下來正常進行CodeFirst操作:生成Migration [name] Upate Database 來源: pass:我會經常修改 不希望被轉載! ...
    一周排行
      -Advertisement-
      Play Games
    • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
    • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
    • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
    • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
    • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
    • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
    • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
    • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
    • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
    • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...