ASP.NET Core 應用配置和啟動“主機”。 主機負責應用程序啟動和生存期管理。 至少,主機配置服務器和請求處理管道。 主機還可以設置日志記錄、依賴關系注入和配置。
本文介紹了 ASP.NET Core Web 主機 (IWebHostBuilder),該主機用于托管 Web 應用。 有關 .NET 泛型主機 (IHostBuilder) 的信息,請參閱 .NET 通用主機。
創(chuàng)建使用 IWebHostBuilder 實例的主機。 通常在應用的入口點來執(zhí)行 Main 方法。 在項目模板中,Main 位于 Program.cs。 典型的 Program.cs 調用 CreateDefaultBuilder 以開始設置主機:
C#
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 執(zhí)行下列任務:
ConfigureAppConfiguration、ConfigureLogging 以及 IWebHostBuilder 的其他方法和擴展方法可重寫和增強 CreateDefaultBuilder 定義的配置。 下面是一些示例:
內容根確定主機搜索內容文件(如 MVC 視圖文件)的位置。 應用從項目的根文件夾啟動時,會將項目的根文件夾用作內容根。 這是 Visual Studio 和 dotnet new 模板中使用的默認值。
有關應用配置的詳細信息,請參閱 ASP.NET Core 中的配置。
備注
作為使用靜態(tài) CreateDefaultBuilder 方法的替代方法,從 WebHostBuilder 創(chuàng)建主機是一種受 ASP.NET Core 2.x 支持的方法。 有關詳細信息,請參閱 ASP.NET Core 1.x 選項卡。
設置主機時,可以提供配置和 ConfigureServices 方法。 如果指定 Startup 類,必須定義 Configure 方法。 有關更多信息,請參見ASP.NET Core 中的應用啟動。 多次調用 ConfigureServices 將追加到另一個。 多次調用 WebHostBuilder 上的 Configure 或 UseStartup 將替換以前的設置。
WebHostBuilder 依賴于以下的方法設置主機配置值:
主機使用任何一個選項設置上一個值。 有關詳細信息,請參閱下一部分中的重寫配置。
在主機構造期間調用 UseStartup 或 Configure 時,會自動設置 IHostingEnvironment.ApplicationName 屬性。 該值設置為包含應用入口點的程序集的名稱。 要顯式設置值,請使用 WebHostDefaults.ApplicationKey:
密鑰:applicationName類型:string默認值:包含應用入口點的程序集的名稱。設置使用:UseSetting環(huán)境變量:ASPNETCORE_APPLICATIONNAME
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
此設置控制啟動錯誤的捕獲。
鍵:captureStartupErrors類型:布爾型(true 或 1)默認值:默認為 false,除非應用使用 Kestrel 在 IIS 后方運行,其中默認值是 true。設置使用:CaptureStartupErrors環(huán)境變量:ASPNETCORE_CAPTURESTARTUPERRORS
當 false 時,啟動期間出錯導致主機退出。 當 true 時,主機在啟動期間捕獲異常并嘗試啟動服務器。
C#
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
此設置確定 ASP.NET Core 開始搜索內容文件,如 MVC 視圖等。
鍵:contentRoot類型:string默認值:默認為應用程序集所在的文件夾。設置使用:UseContentRoot環(huán)境變量:ASPNETCORE_CONTENTROOT
內容根也用作 Web 根設置的基路徑。 如果路徑不存在,主機將無法啟動。
C#
WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")
確定是否應捕獲詳細錯誤。
鍵:detailedErrors類型:布爾型(true 或 1)默認值:false設置使用:UseSetting環(huán)境變量:ASPNETCORE_DETAILEDERRORS
啟用(或當環(huán)境設置為 Development )時,應用捕獲詳細的異常。
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
設置應用的環(huán)境。
鍵:環(huán)境類型:string默認值:生產設置使用:UseEnvironment環(huán)境變量:ASPNETCORE_ENVIRONMENT
環(huán)境可以設置為任何值。 框架定義的值包括 Development``Staging 和 Production。 值不區(qū)分大小寫。 默認情況下,從 ASPNETCORE_ENVIRONMENT 環(huán)境變量讀取環(huán)境。 使用 Visual Studio 時,可能會在 launchSettings.json 文件中設置環(huán)境變量。 有關更多信息,請參見在 ASP.NET Core 中使用多個環(huán)境。
C#
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
設置應用的承載啟動程序集。
鍵:hostingStartupAssemblies類型:string默認值:空字符串設置使用:UseSetting環(huán)境變量:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
承載啟動程序集的以分號分隔的字符串在啟動時加載。
雖然配置值默認為空字符串,但是承載啟動程序集會始終包含應用的程序集。 提供承載啟動程序集時,當應用在啟動過程中生成其公用服務時將它們添加到應用的程序集加載。
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
設置 HTTPS 重定向端口。 用于強制實施 HTTPS。
鍵:https_port;類型:字符串; 默認值:未設置默認值。 設置使用:UseSetting 環(huán)境變量:ASPNETCORE_HTTPS_PORT
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")
承載啟動程序集的以分號分隔的字符串在啟動時排除。
鍵:hostingStartupExcludeAssemblies類型:string默認值:空字符串設置使用:UseSetting環(huán)境變量:ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
指示主機是否應該偵聽使用 WebHostBuilder 配置的 URL,而不是使用 IServer 實現(xiàn)配置的 URL。
鍵:preferHostingUrls類型:布爾型(true 或 1)默認值:true設置使用:PreferHostingUrls環(huán)境變量:ASPNETCORE_PREFERHOSTINGURLS
C#
WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(false)
阻止承載啟動程序集自動加載,包括應用的程序集所配置的承載啟動程序集。 有關更多信息,請參見在 ASP.NET Core 中使用承載啟動程序集。
鍵:preventHostingStartup類型:布爾型(true 或 1)默認值:false設置使用:UseSetting環(huán)境變量:ASPNETCORE_PREVENTHOSTINGSTARTUP
C#
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
指示 IP 地址或主機地址,其中包含服務器應針對請求偵聽的端口和協(xié)議。
鍵:urls類型:string默認: http://localhost:5000設置使用:UseUrls環(huán)境變量:ASPNETCORE_URLS
設置為服務器應響應的以分號分隔 (;) 的 URL 前綴列表。 例如 http://localhost:123。 使用“*”指示服務器應針對請求偵聽的使用特定端口和協(xié)議(例如 http://*:5000)的 IP 地址或主機名。 協(xié)議(http:// 或 https://)必須包含每個 URL。 不同的服務器支持的格式有所不同。
C#
WebHost.CreateDefaultBuilder(args)
.UseUrls("http://*:5000;http://localhost:5001;https://hostname:5002")
Kestrel 具有自己的終結點配置 API。 有關更多信息,請參見ASP.NET Core 中的 Kestrel Web 服務器實現(xiàn)。
指定等待 Web 主機關閉的時長。
鍵:shutdownTimeoutSeconds類型:int默認值:5設置使用:UseShutdownTimeout環(huán)境變量:ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
雖然鍵使用 UseSetting 接受 int(例如 .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")),但是 UseShutdownTimeout 擴展方法采用 TimeSpan。
在超時時間段中,托管:
如果在所有托管服務停止之前就達到了超時時間,則會在應用關閉時會終止剩余的所有活動的服務。即使沒有完成處理工作,服務也會停止。 如果停止服務需要額外的時間,請增加超時時間。
C#
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
確定要在其中搜索 Startup 類的程序集。
鍵:startupAssembly類型:string默認值:應用的程序集設置使用:UseStartup環(huán)境變量:ASPNETCORE_STARTUPASSEMBLY
按名稱(string)或類型(TStartup)的程序集可以引用。 如果調用多個 UseStartup 方法,優(yōu)先選擇最后一個方法。
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")
C#
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
設置應用的靜態(tài)資產的相對路徑。
鍵:webroot類型:string默認值:如果未指定,默認值是“(Content Root)/wwwroot”(如果該路徑存在)。 如果該路徑不存在,則使用無操作文件提供程序。設置使用:UseWebRoot環(huán)境變量:ASPNETCORE_WEBROOT
C#
WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")
使用配置可以配置 Web 主機。 在下面的示例中,主機配置是根據(jù)需要在 hostsettings.json 文件中指定。 命令行參數(shù)可能會重寫從 hostsettings.json 文件加載的任何配置。 生成的配置(在 config中)用于通過 UseConfiguration 配置主機。 IWebHostBuilder 配置會添加到應用配置中,但反之不亦然—ConfigureAppConfiguration 不影響 IWebHostBuilder 配置。
先用 hostsettings.json config 重寫 UseUrls 提供的配置,再用命令行參數(shù) config:
C#
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:
JSON
{
urls: "http://*:5005"
}
備注
UseConfiguration 擴展方法當前不能分析由 GetSection 返回的配置部分(例如 .UseConfiguration(Configuration.GetSection("section"))。 GetSection 方法將配置鍵篩選到所請求的部分,但將節(jié)名稱保留在鍵上(例如 section:urls、section:environment)。 UseConfiguration 方法需要鍵來匹配 WebHostBuilder 鍵(例如 urls、environment)。 鍵上存在的節(jié)名稱阻止節(jié)的值配置主機。 將在即將發(fā)布的版本中解決此問題。 有關詳細信息和解決方法,請參閱將配置節(jié)傳入到 WebHostBuilder.UseConfiguration 使用完整的鍵。
UseConfiguration 只將所提供的 IConfiguration 中的密鑰復制到主機生成器配置中。 因此,JSON、INI 和 XML 設置文件的設置 reloadOnChange: true 沒有任何影響。
若要指定在特定的 URL 上運行的主機,所需的值可以在執(zhí)行 dotnet 運行時從命令提示符傳入。 命令行參數(shù)重寫 hostsettings.json 文件中的 urls 值,且服務器偵聽端口 8080:
console
dotnet run --urls "http://*:8080"
運行
Run 方法啟動 Web 應用并阻止調用線程,直到關閉主機:
C#
host.Run();
Start
通過調用 Start 方法以非阻止方式運行主機:
C#
using (host)
{
host.Start();
Console.ReadLine();
}
如果 URL 列表傳遞給 Start 方法,該列表偵聽指定的 URL:
C#
var urls = new List<string>()
{
"http://*:5000",
"http://localhost:5001"
};
var host = new WebHostBuilder()
.UseKestrel()
.UseStartup<Startup>()
.Start(urls.ToArray());
using (host)
{
Console.ReadLine();
}
應用可以使用通過靜態(tài)便捷方法預配置的 CreateDefaultBuilder 默認值初始化并啟動新的主機。 這些方法在沒有控制臺輸出的情況下啟動服務器,并使用 WaitForShutdown 等待中斷(Ctrl-C/SIGINT 或 SIGTERM):
Start(RequestDelegate app)
從 RequestDelegate 開始:
C#
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 發(fā)出請求,接收響應“Hello World!” WaitForShutdown 受到阻止,直到發(fā)出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 消息并等待 keypress 退出。
Start(string url, RequestDelegate app)
從 URL 和 RequestDelegate 開始:
C#
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> routeBuilder)
使用 IRouteBuilder 的實例 (Microsoft.AspNetCore.Routing) 用于路由中間件:
C#
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();
}
該示例中使用以下瀏覽器請求:
請求 | 響應 |
---|---|
http://localhost:5000/hello/Martin | Hello, Martin! |
http://localhost:5000/buenosdias/Catrina | Buenos dias, Catrina! |
http://localhost:5000/throw/ooops! | 使用“ooops!”字符串引發(fā)異常 |
http://localhost:5000/throw | 使用“Uh oh!”字符串引發(fā)異常 |
http://localhost:5000/Sante/Kevin | Sante, Kevin! |
http://localhost:5000 | Hello World! |
WaitForShutdown 受到阻止,直到發(fā)出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 消息并等待 keypress 退出。
Start(string url, Action<IRouteBuilder> routeBuilder)
使用 URL 和 IRouteBuilder 實例:
C#
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:
C#
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 發(fā)出請求,接收響應“Hello World!” WaitForShutdown 受到阻止,直到發(fā)出中斷(Ctrl-C/SIGINT 或 SIGTERM)。 應用顯示 Console.WriteLine 消息并等待 keypress 退出。
StartWith(string url, Action<IApplicationBuilder> app)
提供 URL 和委托以配置 IApplicationBuilder:
C#
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<IApplicationBuilder> app) 相同的結果,除非應用在 http://localhost:8080 上響應。
IHostingEnvironment 接口提供有關應用的 Web 承載環(huán)境的信息。 使用構造函數(shù)注入獲取 IHostingEnvironment 以使用其屬性和擴展方法:
C#
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
}
}
基于約定的方法可以用于在啟動時基于環(huán)境配置應用。 或者,將 IHostingEnvironment 注入到 Startup 構造函數(shù)用于 ConfigureServices:
C#
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;
}
}
備注
除了 IsDevelopment 擴展方法,IHostingEnvironment 提供 IsStaging、IsProduction 和 IsEnvironment(string environmentName) 方法。 有關更多信息,請參見在 ASP.NET Core 中使用多個環(huán)境。
IHostingEnvironment 服務還可以直接注入到 Configure 方法以設置處理管道:
C#
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;
}
創(chuàng)建自定義中間件時可以將 IHostingEnvironment 注入 Invoke 方法:
C#
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;
}
IApplicationLifetime 允許后啟動和關閉活動。 接口上的三個屬性是用于注冊 Action 方法(用于定義啟動和關閉事件)的取消標記。
取消標記 | 觸發(fā)條件 |
---|---|
ApplicationStarted | 主機已完全啟動。 |
ApplicationStopped | 主機正在完成正常關閉。 應處理所有請求。 關閉受到阻止,直到完成此事件。 |
ApplicationStopping | 主機正在執(zhí)行正常關閉。 仍在處理請求。 關閉受到阻止,直到完成此事件。 |
C#
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 正常關閉應用:
C#
public class MyClass
{
private readonly IApplicationLifetime _appLifetime;
public MyClass(IApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
如果應用環(huán)境為“開發(fā)”,則 CreateDefaultBuilder 將 ServiceProviderOptions.ValidateScopes 設為 true。
若將 ValidateScopes 設為 true,默認服務提供程序會執(zhí)行檢查來驗證以下內容:
調用 BuildServiceProvider 時,會創(chuàng)建根服務提供程序。 在啟動提供程序和應用時,根服務提供程序的生存期對應于應用/服務的生存期,并在關閉應用時釋放。
有作用域的服務由創(chuàng)建它們的容器釋放。 如果作用域創(chuàng)建于根容器,則該服務的生存會有效地提升至單一實例,因為根容器只會在應用/服務關閉時將其釋放。 驗證服務作用域,將在調用 BuildServiceProvider 時收集這類情況。
若要始終驗證作用域(包括在生存環(huán)境中驗證),請使用主機生成器上的 UseDefaultServiceProvider配置 ServiceProviderOptions:
C#
WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})
更多建議: