1.前言 ASP.NET Core應用程式可以配置和啟動主機(Host)。主機負責應用程式啟動和生存期管理,配置伺服器和請求處理管道。主機還可以設置日誌記錄、依賴關係註入和配置。而host主機又包括Web主機(IWebHostBuilder)和通用主機(IHostBuilder)。該章節主要介紹了用 ...
1.前言
ASP.NET Core應用程式可以配置和啟動主機(Host)。主機負責應用程式啟動和生存期管理,配置伺服器和請求處理管道。主機還可以設置日誌記錄、依賴關係註入和配置。而host主機又包括Web主機(IWebHostBuilder)和通用主機(IHostBuilder)。該章節主要介紹了用於托管Web應用的Web主機。對於其他類型的應用,請使用通用主機。
2.設置主機
創建使用IWebHostBuilder實例的主機。通常在應用程式的入口點來執行Main方法。在項目模板中,Main位於Program.cs。典型應用預設調用CreateDefaultBuilder來開始創建主機:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
2.1執行下列任務
調用CreateDefaultBuilder的代碼位於名為CreateWebHostBuilder的方法中,這讓它區分於 Main中對生成器對象調用Run的代碼。CreateDefaultBuilder執行下列任務:
●使用應用程式的托管配置提供應用程式將Kestrel伺服器配置為Web伺服器。
●將內容根設置為由 Directory.GetCurrentDirectory返回的路徑。
●通過以下對象載入主機配置:
○首碼為ASPNETCORE_的環境變數(例如,ASPNETCORE_ENVIRONMENT)。
○命令行參數。
●按以下順序載入應用程式配置:
○appsettings.json。
○appsettings.{Environment}.json。
○應用在使用入口程式集的Development環境中運行時的機密管理器。
○環境變數。
○命令行參數。
●配置控制台和調試輸出的日誌記錄。日誌記錄包含appsettings.json或appsettings.{Environment}.json文件的日誌記錄配置部分中指定的日誌篩選規則。
●使用ASP.NET Core模塊在IIS後面運行時,CreateDefaultBuilder會啟用IIS集成,這會配置應用程式的基址和埠。IIS集成還配置應用程式以捕獲啟動錯誤。
●如果應用環境為“開發(Development)”,請將ServiceProviderOptions.ValidateScopes設為true。
2.2重寫和增強定義的配置
ConfigureAppConfiguration、ConfigureLogging以及IWebHostBuilder的其他方法和擴展方法可重寫和增強CreateDefaultBuilder定義的配置。下麵是一些示例:
●ConfigureAppConfiguration:用於指定應用的其他IConfiguration。下麵的ConfigureAppConfiguration調用添加委托,以在appsettings.xml文件中添加應用配置,該示例在Core系列第11章節有演示。可多次調用ConfigureAppConfiguration。請註意,此配置不適用於主機(例如,伺服器URL或環境)。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); });
●ConfigureLogging:ConfigureLogging調用添加委托,將最小日誌記錄級別 (SetMinimumLevel)配置為LogLevel.Warning。此設置重寫CreateDefaultBuilder在appsettings.Development.json和appsettings.Production.json中配置,分別為LogLevel.Debug和LogLevel.Error。可多次調用 ConfigureLogging。
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); });
●ConfigureKestrel:調用ConfigureKestrel來重寫CreateDefaultBuilder在配置Kestrel時建立的30,000,000位元組預設Limits.MaxRequestBodySize:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 20000000; });
設置主機時,可以提供配置和ConfigureServices方法。如果指定Startup類,必須定義Configure方法。
3.主機配置值
WebHostBuilder依賴於以下的方法設置主機配置值:
●主機生成器配置,其中包括格式ASPNETCORE_{configurationKey}的環境變數。例如 ASPNETCORE_ENVIRONMENT。
●UseContentRoot和UseConfiguration等擴展。
●UseSetting和關聯鍵。使用UseSetting設置值時,該值設置為無論何種類型的字元串。
3.1應用程式鍵(名稱)
在主機構造期間調用UseStartup或Configure時,會自動設置 IHostingEnvironment.ApplicationName屬性。該值設置為包含應用入口點的程式集的名稱。要顯式設置值,請使用WebHostDefaults.ApplicationKey(環境變數:ASPNETCORE_APPLICATIONNAME):
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { //應用程式預設名稱為:CoreWeb (也就是項目名稱) string an = env.ApplicationName; ...
} public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args).UseStartup<Startup>() .UseSetting(WebHostDefaults.ApplicationKey, "CoreWeb");
3.2捕獲啟動錯誤
此設置控制啟動錯誤的捕獲。當false時,啟動期間出錯導致主機退出。當true時,主機在啟動期間捕獲異常並嘗試啟動伺服器(環境變數:ASPNETCORE_CAPTURESTARTUPERRORS)。
WebHost.CreateDefaultBuilder(args) .CaptureStartupErrors(true)
3.3內容根
此設置確定ASP.NET Core開始搜索內容文件,如MVC視圖等。內容根也用作Web根設置的基路徑。如果路徑不存在,主機將無法啟動(環境變數:ASPNETCORE_CONTENTROOT)。
WebHost.CreateDefaultBuilder(args) .UseContentRoot("c:\\<content-root>")
3.4詳細錯誤
確定是否應捕獲詳細錯誤。啟用(或當環境設置為Development)時,應用捕獲詳細的異常(環境變數:ASPNETCORE_DETAILEDERRORS)。
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
3.5環境
設置應用程式的環境。環境可以設置為任何值。框架定義的值包括Development、Staging和Production。值不區分大小寫。預設情況下,從ASPNETCORE_ENVIRONMENT環境變數讀取環境。使用Visual Studio時,可能會在launchSettings.json文件中設置環境變數。有關於環境詳情信息,可以移步到Core系列第10章節有參閱(環境變數:ASPNETCORE_ENVIRONMENT)。
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
3.6HTTPS埠
設置HTTPS重定向埠。用於強制實施HTTPS(環境變數:ASPNETCORE_HTTPS_PORT)。
WebHost.CreateDefaultBuilder(args) .UseSetting("https_port", "8080")
3.7伺服器(Kestrel) URL
指示IP地址或主機地址,其中包含伺服器應針對請求偵聽的埠和協議。設置為伺服器應響應的以分號分隔 (;) 的URL首碼列表。例如 http://localhost:123。使用“*”指示伺服器應針對請求偵聽的使用特定埠和協議(例如 http://*:5000)的IP地址或主機名。協議(http://或https://)必須包含每個URL。不同的伺服器支持的格式有所不同(環境變數:ASPNETCORE_URLS)。
WebHost.CreateDefaultBuilder(args) .UseUrls("https://*:5000;https://localhost:5001;https://hostname:5002")
4.重寫配置
使用配置可以配置Web主機。在下麵的示例中,主機配置是根據需要在hostsettings.json文件中指定。命令行參數可能會重寫從hostsettings.json文件載入的任何配置。生成的配置(在config中)用於通過UseConfiguration配置主機。
新建一個hostsettings.json文件,內容如下:
{ "urls": "https://*:5005" }
public static IWebHostBuilder CreateWebHostBuilder(string[] args) { //IConfigurationBuilder的配置主機 var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) //主機配置在hostsettings.json文件中指定 .AddJsonFile("hostsettings.json", optional: true) //輸入的命令行參數可能會重寫從hostsettings.json文件載入的任何配置 .AddCommandLine(args) .Build(); return WebHost.CreateDefaultBuilder(args) .UseUrls("https://*:5001") .UseConfiguration(config) .Configure(app => { //生成的配置委托函數 app.Run(context => context.Response.WriteAsync("Hello, World!")); }); }
上述代碼描述意思是若要指定在特定的URL上運行的主機,所需的值可以在執行dotnet運行時從命令提示符傳入。命令行參數重寫hostsettings.json文件中的urls值,且伺服器偵聽埠8080:
dotnet run --urls "http://*:8080"
主機啟動時,先用hostsettings.json config重寫UseUrls提供的urls參數配置,然後再用命令行參數config重寫hostsettings.json config的urls參數配置。
5.管理主機
管理主題啟動方式有Run和Start兩種。Run方法啟動Web應用程式並阻止調用線程,直到關閉主機。Start方法通過調用自身以非阻止方式運行主機。
//Run CreateWebHostBuilder(args).Build().Run();
//Start:非阻止方式,所有必須加上ReadLine CreateWebHostBuilder(args).Build().Start(); Console.ReadLine();
6.IHostingEnvironment介面
IHostingEnvironment介面提供有關應用的Web承載環境的信息。使用構造函數註入獲取 IHostingEnvironment以使用其屬性和擴展方法:
//示例1: public class CustomFileReader { private readonly IHostingEnvironment _env; public CustomFileReader(IHostingEnvironment env) { _env = env; } public string ReadFile(string filePath) { var fileProvider = _env.WebRootFileProvider; // Process the file here } }
可以用於在啟動時基於環境配置應用程式或者將IHostingEnvironment註入到Startup構造函數,用於ConfigureServices:
//示例2: public class Startup { public Startup(IHostingEnvironment env) { HostingEnvironment = env; } public IHostingEnvironment HostingEnvironment { get; } public void ConfigureServices(IServiceCollection services) { if (HostingEnvironment.IsDevelopment()) { // Development configuration } else { // Staging/Production configuration } var contentRootPath = HostingEnvironment.ContentRootPath; } }
IHostingEnvironment服務還可以直接註入到Configure方法以設置處理管道:
//示例3: public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { // In Development, use the Developer Exception Page app.UseDeveloperExceptionPage(); } else { // In Staging/Production, route exceptions to /error app.UseExceptionHandler("/error"); } var contentRootPath = env.ContentRootPath; }
創建自定義中間件(要瞭解中間件的同學們,可以移步到第四章節學習)時可以將IHostingEnvironment 註入Invoke方法:
public async Task Invoke(HttpContext context, IHostingEnvironment env) { if (env.IsDevelopment()) { // Configure middleware for Development } else { // Configure middleware for Staging/Production } var contentRootPath = env.ContentRootPath; }
7.IApplicationLifetime介面
IApplicationLifetime允許後啟動和關閉活動。介面上的三個屬性是用於註冊Action方法(用於定義啟動和關閉事件)的取消標記。
取消標記 |
觸發條件 |
ApplicationStarted |
主機已完全啟動。 |
ApplicationStopped |
主機正在完成正常關閉。應處理所有請求。 關閉受到阻止,直到完成此事件。 |
ApplicationStopping |
主機正在執行正常關閉。仍在處理請求。關閉受到阻止,直到完成此事件。 |
public class Startup { public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime) { appLifetime.ApplicationStarted.Register(OnStarted); appLifetime.ApplicationStopping.Register(OnStopping); appLifetime.ApplicationStopped.Register(OnStopped); Console.CancelKeyPress += (sender, eventArgs) => { appLifetime.StopApplication(); // Don't terminate the process immediately, wait for the Main thread to exit gracefully. eventArgs.Cancel = true; }; } private void OnStarted() { // Perform post-startup activities here } private void OnStopping() { // Perform on-stopping activities here } private void OnStopped() { // Perform post-stopped activities here } }
StopApplication是請求應用終止的意思。以下類在調用類的Shutdown方法時使用StopApplication正常關閉應用:
public class MyClass { private readonly IApplicationLifetime _appLifetime; public MyClass(IApplicationLifetime appLifetime) { _appLifetime = appLifetime; } public void Shutdown() { _appLifetime.StopApplication(); } }
8.作用域驗證
如果應用環境為“開發(Development)”,則CreateDefaultBuilder將ServiceProviderOptions.ValidateScopes設為true。若將ValidateScopes設為true,預設服務提供應用程式會執行檢查來驗證以下內容:
●作用域服務不能直接或間接地從根服務提供者解析。
●作用域服務不會直接或間接地註入到單例中(服務的生命周期)。
若要始終驗證作用域(包括在生命周期環境中驗證),請使用主機生成器上的 UseDefaultServiceProvider配置ServiceProviderOptions:
WebHost.CreateDefaultBuilder(args) .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = true; })
參考文獻:
ASP.NET Core Web主機