翻譯自 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-5.0web
ASP.NET Core 應用程序配置和啓動一個 Host。Host 負責應用程序的啓動和生命週期的管理。至少的,Host 配置一個服務器和一個請求處理管道。Host 也會設置日誌,依賴注入和配置。json
這篇文章覆蓋了 Web Host,任然是隻是向後兼容可用。 Generic Host 推薦用於全部類型的應用程序。api
使用 IWebHostBuilder 的實例建立一個 Host。通常會在應用程序的入口點 Main 方法中建立。瀏覽器
在工程模板中,Main 方法位於 Program.cs 中。典型的應用程序調用 CreateDefaultBuilder 啓動配置一個 Host:服務器
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>(); }
代碼中調用 CreateDefaultBuilder 的是在一個叫作 CreateWebHostBuilder 的方法中,這個方法從 Main 中分離出來,在 Main 方法中在 builder 對象上調用 Run 方法。這中分離是有必須的,若是你使用了 Entity Framework Core tools。這個工具指望找到一個 CreateWebHostBuilder 方法,以便能沒必要運行應用程序就可以在設計的時候配置 Host。一種途徑是實現接口 IDesignTimeDbContextFactory。更多信息,查看 Design-time DbContext Creation。app
CreateDefaultBuilder 執行了如下任務:框架
CreateDefaultBuilder 定義的配置能夠被覆蓋和使用 ConfigureAppConfiguration,ConfigureLogging 和其它方法及 IWebHostBuilder 的擴展方法擴展。下面是幾個例子:async
WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); }) ...
WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); }) ...
WebHost.CreateDefaultBuilder(args) .ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 20000000; });
content root 決定了 Host 在哪裏搜索內容文件,例如 MVC 視圖文件。當應用程序從工程根目錄啓動的時候,工程根目錄被用做內容根目錄。這在 Visual Studio 和 dotnet new templates 默認使用。ide
更多關於應用程序配置的信息,查看 Configuration in ASP.NET Core。工具
注意
做爲一種使用靜態 CreateDefaultBuilder 方法的途徑,從 WebHostBuilder 建立一個 Host 在 ASP.NET Core 2.x 中是受支持的。
當設置一個主機的時候,能夠提供 Configure 和 ConfigureServices 這兩個方法。若是一個 Startup 方法被指定了,它必須定義 Configure 方法。更多信息,查看 App startup in ASP.NET Core 。屢次調用 ConfigureServices 將會附加到另一個上面。在 WebHostBuilder 上屢次調用 Configure 或者 UseStartup 將會替換以前的設置。
WebHostBuilder 依賴下面的方法設置主機配置值:
主機使用最後設置值得選項。更多信息查看,Override configuration。
Application Key (Name)
當 UseStartup 或者 Configure 在主機構造方法中調用的時候,IWebHostEnvironment.ApplicationName 屬性會自動設置。值被設置爲包含應用程序入口點的程序集的名稱。顯式的設置,可使用 WebHostDefaults.ApplicationKey:
Key: applicationName
Type: string
Default: 包含應用程序入口點程序集的名稱
Set using: UseSetting
Environment variable: ASPNETCORE_APPLICATIONNAME
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
設置捕獲啓動錯誤的控制
Key: captureStartupErrors
Type: bool (true or 1)
Default: 默認爲 false,除非應用程序使用 Kestrel 運行在 IIS 以後,這時默認是 true
Set using: CaptureStartupErrors
Environment variable: ASPNETCORE_CAPTURESTARTUPERRORS
當設置爲 false 時,啓動過程當中的錯誤會致使主機退出。當設置爲 true 時,主機會捕獲啓動過程當中的異常,而且試圖啓動服務器。
WebHost.CreateDefaultBuilder(args) .CaptureStartupErrors(true)
這個設置決定了 ASP.NET Core 開始搜索內容文件的位置。
Key: contentRoot
Type: string
Default: 默認是應用程序程序集所在的目錄
Set using: UseContentRoot
Environment variable: ASPNETCORE_CONTENTROOT
content root 也被用做 web root 的基本路徑。若是 content root 路徑不存在,主機就會啓動失敗。
WebHost.CreateDefaultBuilder(args) .UseContentRoot("c:\\<content-root>")
更多信息,請查看:
決定是否應該詳細錯誤信息
Key: detailedErrors
Type: bool (treu 或者 1)
Default: false
Set using: UseSetting
Environment variable: ASPNETCORE_DETAILEDERRORS
當使能的時候(或者 Environment 被設置爲 Development 的時候),應用程序會捕獲異常詳細信息。
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
設置應用程序環境
Key: environment
Type: string
Default: Production
Set using: UseEnvironment
Environment variable: ASPNETCORE_ENVIRONMENT
environmenmt 能夠被設置爲任意的值。框架定義的值包括 Development,Staging 和 Production。值不區分大小寫。默認的,Environment 從 ASPNETCORE_ENVIRONMENT 環境變量中讀取。當使用 Visual Studio 時,環境變量可能在 lauchSetting.json 文件中設置。更過信息,請查看: Use multiple environments in ASP.NET Core。
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
設置應用程序託管啓動程序集
Key: hostingStartupAssemblies
Type: string
Default: Empty string
Set using: UseSetting
Environment variable: ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
以逗號分隔的字符串,啓動時加載的託管的啓動程序集
儘管配置值被設置爲空字符串,託管程序集老是包含應用程序程序集。當提供了託管啓動程序集,它們在應用程序啓動時建立公共服務時被添加到應用程序程序集。
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
設置 HTTPS 重定向端口。使用 enforcing HTTPS。
Key: https_port
Type: string
Defalut: 默認無設置
Set using: UseSetting
Environment variable: ASPNETCORE_HTTPS_PORT
WebHost.CreateDefaultBuilder(args) .UseSetting("https_port", "8080")
冒號分隔的字符串,啓動時排除託管啓動程序集
Key: hostingStartupExcludeAssemblies
Type: string
Default: Empty string
Set using: UseSetting
Environment variable: ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
代表主機是否應該在使用 WebHostBuilder 配置的 URLs 上監聽,而不是 IServer 實現配置的 URLs
Key: preferHostingUrls
Type: bool (true 或者 1)
Default: true
Set using: PreferHostingUrls
Environment variable: ASPNETCORE_PREFERHOSTINGURLS
WebHost.CreateDefaultBuilder(args) .PreferHostingUrls(false)
阻止自動加載託管啓動程序集,包括應用程序程序集配置的託管啓動程序集。更多信息查看,Use hosting startup assemblies in ASP.NET Core。
Key: preventHostingStartup
Type: bool (true 或者 1)
Default: false
Set using: UseSetting
Environment variable: ASPNETCORE_PREVENTHOSTINGSTARTUP
WebHost.CreateDefaultBuilder(args) .UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
代表帶有端口和協議的 IP 地址或者主機地址是否應該被服務器監聽請求
Key: urls
Type: string
Default: http://localhost:5000
Set using: UseUrls
Environment variable: ASPNETCORE_URLS
設置一組服務器應該響應的冒號(;)分隔的 URL 前綴。例如,http://localhost:123。使用 "*" 代表服務器是否應該監放任意使用特定端口和協議(例如,http://*:5000)的 IP 地址或者主機地址。協議 (http:// 或者 https://) 必須包含在每個 URL 中。支持的格式因服務器不一樣而不一樣。
WebHost.CreateDefaultBuilder(args) .UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
Kestrel 有它本身的 endpoint 配置 API。更多信息查看,Configure endpoints for the ASP.NET Core Kestrel web server。
指定等待 Web Host 關閉的超時時間
Key: shutdownTimeoutSeconds
Type: int
Default: 5
Set using: UseShutdownTimeout
Environment variable: ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
儘管使用 UseSetting 能夠接受鍵爲 int 的值(例如,.UseSetting(WebHostDefaults.ShutdownTimeoutKey,"10")),UseShutdownTimeout 帶有 TimeSpan 參數。
在超時時間內,主機會:
若是在全部服務中止以前超時了,任何活動的服務在應用程序關閉時都會中止。即便服務沒有完成處理也會被中止。若是服務須要更多的時間去中止,增長超時時間。
WebHost.CreateDefaultBuilder(args) .UseShutdownTimeout(TimeSpan.FromSeconds(10))
決定搜索 Startup 類的程序集
Key: startupAssembly
Type: string
Default: 應用程序程序集
Set using: UseStartup
Environment variable: ASPNETCORE_STARTUPASSEMBLY
能夠指定程序的名稱(string)或者類型 (TStartup)。若是多個 UseStartup 方法被調用,則最後一個優先級最高:
WebHost.CreateDefaultBuilder(args) .UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
設置應用程序靜態資源的相對路徑
Key: webroot
Type: string
Default: 默認是 wwwroot。路基 {contentroot}/wwwroot 必須存在。若是路徑不存在,一個 no-op 文件提供器將被使用。
WebHost.CreateDefaultBuilder(args) .UseWebRoot("public")
更多信息查看:
使用 Configuration 配置 Web Host。在下面的例子中,host 配置在 hostsetting.json 文件中是可選指定的。任何從 hostsetting.json 文件中加載的配置可能會被命令行參數覆蓋。編譯的配置(in config)使用 UseConfiguration 來配置主機。IWebHostBuilder 配置被添加到應用程序配置中,可是相反的就不是,ConfigureAppConfigureation 不會影響 IWebHostBuilder 配置。
覆蓋 UseUrls 提供的配置優先使用 hostsettings.json 配置,其次是命令行參數配置:
public class Program { public static void Main(string[] args) { CreateWebHostBuilder(args).Build().Run(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) { var config = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("hostsettings.json", optional: true) .AddCommandLine(args) .Build(); return WebHost.CreateDefaultBuilder(args) .UseUrls("http://*:5000") .UseConfiguration(config) .Configure(app => { app.Run(context => context.Response.WriteAsync("Hello, World!")); }); } }
hostsettings.json:
{ urls: "http://*:5005" }
注意
UseConfiguration 只會複製 IConfiguration 提供的鍵值到 host builder 配置。所以,設置 reloadOnChange: true 爲 JSON,INI,和 XML 設置文件沒有影響。
指定主機在一個特定的 URL 上運行,指望的值能夠在運行 dotnet run 時命令行提示中傳入。命令行參數覆蓋了來自 hostsettings.json 中的 urls 值,服務器在 8080 端口監聽:
dotnet run --urls "http://*:8080"
Run 方法啓動 web 應用程序並阻塞調用線程直到 Host 關閉:
host.Run();
經過調用它的 Start 方法以 non-blocking 方式運行 Host:
using (host) { host.Start(); Console.ReadLine(); }
若是一組 URLs 傳遞給 Start 方法,它就會監聽這組指定的 URLs:
var urls = new List<string>() { "http://*:5000", "http://localhost:5001" }; var host = new WebHostBuilder() .UseKestrel() .UseStartup<Startup>() .Start(urls.ToArray()); using (host) { Console.ReadLine(); }
應用程序可使用預設值的默認 CreateDefaultBuilder 使用一個靜態約定的方法初始化和啓動一個新的 Host。這些方法啓動服務器時沒有控制檯輸出,使用 WaitForShutdown 等待終止(Ctrl-C/SIGINT 或者 SIGTERM):
Start(RequestDelegate app)
使用 RequestDelegate 啓動:
using (var host = WebHost.Start(app => app.Response.WriteAsync("Hello, World!"))) { Console.WriteLine("Use Ctrl-C to shutdown the host..."); host.WaitForShutdown(); }
在瀏覽器中發送一個請求 http://localhost:5000 接收到 "Hello World!" 響應,WaitForShutdown 阻塞了直到一個結束信號 (Ctrl-C/SIGINT 或者 SIGTERM) 出現。應用程序顯示了 Console.WriteLine 信息,等待按鍵退出。
Start(string url, RequestDelegate app)
使用一個 URL 和 RequestDelegate 啓動應用程序:
using (var host = WebHost.Start("http://localhost:8080", app => app.Response.WriteAsync("Hello, World!"))) { Console.WriteLine("Use Ctrl-C to shutdown the host..."); host.WaitForShutdown(); }
和 Start(RequestDelegate app) 生成一樣的結果,指望應用程序在 http://localhost:8080 上響應。
Start(Action <IRouteBuilder> routerBuilder)
使用 IRouteBuilder (Microsoft.AspNetCore.Routing) 的實例使用 routing 中間件:
using (var host = WebHost.Start(router => router .MapGet("hello/{name}", (req, res, data) => res.WriteAsync($"Hello, {data.Values["name"]}!")) .MapGet("buenosdias/{name}", (req, res, data) => res.WriteAsync($"Buenos dias, {data.Values["name"]}!")) .MapGet("throw/{message?}", (req, res, data) => throw new Exception((string)data.Values["message"] ?? "Uh oh!")) .MapGet("{greeting}/{name}", (req, res, data) => res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!")) .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!")))) { Console.WriteLine("Use Ctrl-C to shutdown the host..."); host.WaitForShutdown(); }
對上面的示例使用下面的瀏覽器請求:
Request | Response |
http://localhost:5000/hello/Martin | Hello,Martin! |
http://localhost:5000/buenosdias/Catrina | Buenos dias,Catrina! |
http://localhost:5000/throw/ooops! | Throw an exception with string "ooops!" |
http://localhost:5000/throw | Throw an exception with string "Uh oh!" |
http://localhost:5000/Sante/Kevin | Sante,Kevin! |
http://localhost:5000 | Hello World! |
WaitForShutdown 阻塞直到結束信號(Ctrl-C/SIGINT 或者 SIGTERM)出現。應用程序顯示 Console.WriteLine 信息,等待按鍵按下退出。
Start(string url, Action<IRouteBuilder> routeBuilder)
使用 URL 和 IRouterBuilder 實例:
using (var host = WebHost.Start("http://localhost:8080", router => router .MapGet("hello/{name}", (req, res, data) => res.WriteAsync($"Hello, {data.Values["name"]}!")) .MapGet("buenosdias/{name}", (req, res, data) => res.WriteAsync($"Buenos dias, {data.Values["name"]}!")) .MapGet("throw/{message?}", (req, res, data) => throw new Exception((string)data.Values["message"] ?? "Uh oh!")) .MapGet("{greeting}/{name}", (req, res, data) => res.WriteAsync($"{data.Values["greeting"]}, {data.Values["name"]}!")) .MapGet("", (req, res, data) => res.WriteAsync("Hello, World!")))) { Console.WriteLine("Use Ctrl-C to shut down the host..."); host.WaitForShutdown(); }
生成和 Start(Action<IRouteBuilder> routeBuilder) 相同的結果,指望應用程序在 http://localhost:8080 上響應。
StartWith(Action<IApplicationBuilder> app)
提供一個代理配置一個 IApplicationBuilder:
using (var host = WebHost.StartWith(app => app.Use(next => { return async context => { await context.Response.WriteAsync("Hello World!"); }; }))) { Console.WriteLine("Use Ctrl-C to shut down the host..."); host.WaitForShutdown(); }
在瀏覽器中請求 http://localhost:5000 接收到 "Hello World!" 響應,WaitForShutdown 阻塞直到一個結束信號(Ctrl-C/SIGINT 或者 SIGTERM)發出。應用程序顯示了 Console.WriteLine 信息,等待按鍵按下退出。
StartWith(string url, Action<IApplicationBuilder> app)
提供一個 url 和一個代理配置 IApplicationBuilder:
using (var host = WebHost.StartWith("http://localhost:8080", app => app.Use(next => { return async context => { await context.Response.WriteAsync("Hello World!"); }; }))) { Console.WriteLine("Use Ctrl-C to shut down the host..."); host.WaitForShutdown(); }
結果和 StartWith(Action<IApplicatonBuilder> app) 相同的結果,指望在應用程序在 http://localhost:8080 上響應。
IWebHostEnvironment 接口提供了關於應用程序 web 託管環境的信息。使用 constructor injection 訪問 IWebHostEnvironment 保證使用它的屬性和擴展方法:
public class CustomFileReader { private readonly IWebHostEnvironment _env; public CustomFileReader(IWebHostEnvironment env) { _env = env; } public string ReadFile(string filePath) { var fileProvider = _env.WebRootFileProvider; // Process the file here } }
一個 convention-based approach 能夠基於環境在啓動時用來配置應用程序。或者,在 ConfigureServices 中將 IWebHostEnvironment 注入到 Startup 構造方法使用:
public class Startup { public Startup(IWebHostEnvironment env) { HostingEnvironment = env; } public IWebHostEnvironment HostingEnvironment { get; } public void ConfigureServices(IServiceCollection services) { if (HostingEnvironment.IsDevelopment()) { // Development configuration } else { // Staging/Production configuration } var contentRootPath = HostingEnvironment.ContentRootPath; } }
注意
除了 IsDevelopment 擴展方法外,IWebHostEnvironment 提供了 IsStaging,IsProduction 和 IsEnvironment(string environment) 方法。更多信息查看,Use multiple environments in ASP.NET Core。
IWebHostEnvironment 服務也能夠直接注入到 Configure 方法用來設置處理管道:
public void Configure(IApplicationBuilder app, IWebHostEnvironment 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; }
當建立自定義中間件(middleware)的時候,IWebHostEnvironment 能夠被注入到 Invoke 方法:
IHostApplicationLifetime 容許 post-startup 和 關閉。接口的三個屬性是取消令牌,用來註冊定義啓動和關閉時間的Action 方法。
Cancellation Token | Triggered when... |
ApplicationStarted | 主機已經徹底啓動 |
ApplicationStopped | 主機已經徹底正常關閉。全部的請求應該已經處理完畢。關閉阻塞直到這個事件完成。 |
ApplicationStopping | 主機正在正常關閉。請求可能仍然正在處理。關閉阻塞直到這個事件完成。 |
public class Startup { public void Configure(IApplicationBuilder app, IHostApplicationLifetime 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 請求結束應用程序。下面的類使用 StopApplication 正常關閉應用程序當類的 Shutdown 方法被調用的時候:
public class MyClass { private readonly IHostApplicationLifetime _appLifetime; public MyClass(IHostApplicationLifetime appLifetime) { _appLifetime = appLifetime; } public void Shutdown() { _appLifetime.StopApplication(); } }
當應用程序的環境是 Development 的時候,CreateDefaultBuilder 設置 ServiceProviderOptions.ValidateScopes 爲 true。
當 ValidateScopes 被設置爲 true 時,默認的服務提供器執行檢查驗證:
根服務提供器在 BuildServiceProvider 被調用時建立。根服務提供器的生命週期和應用程序/服務器的生命週期一致,當提供器和應用程序一塊兒啓動,在應用程序關閉時釋放。
Scoped 服務由建立它的容器釋放。若是一個 scoped 服務在根容器中建立,服務的生命週期會有效的提高爲單例,由於它只有在應用程/服務器關閉的時候會釋放掉。在調用 BuildServiceProvider 的時候,驗證服務會捕捉這些狀況。
爲了在 Production 環境中老是包含 validate scopes,在 Host builer 上使用 UseDefaultServiceProvider 配置 ServiceProviderOptions:
WebHost.CreateDefaultBuilder(args) .UseDefaultServiceProvider((context, options) => { options.ValidateScopes = true; })