翻译自 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; })