1.前言
ASP.NET Core应用程序可以配置和启动主机(Host)。主机负责应用程序启动和生存期管理,配置服务器和请求处理管道。主机还可以设置日志记录、依赖关系注入和配置。而host主机又包括Web主机(IWebHostBuilder)和通用主机(IHostBuilder)。该章节主要介绍了用于托管Web应用的Web主机。对于其他类型的应用,请使用通用主机。
2.设置主机
创建使用IWebHostBuilder实例的主机。通常在应用程序的入口点来执行Main方法。在项目模板中,Main位于Program.cs。典型应用默认调用CreateDefaultBuilder来开始创建主机:
1. public class Program 2. { 3. public static void Main(string[] args) 4. { 5. CreateWebHostBuilder(args).Build().Run(); 6. } 7. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 8. WebHost.CreateDefaultBuilder(args) 9. .UseStartup<Startup>(); 10. }
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或环境)。
1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 2. WebHost.CreateDefaultBuilder(args) 3. .ConfigureAppConfiguration((hostingContext, config) => 4. { 5. config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); 6. });
●ConfigureLogging:ConfigureLogging调用添加委托,将最小日志记录级别 (SetMinimumLevel)配置为LogLevel.Warning。此设置重写CreateDefaultBuilder在appsettings.Development.json和appsettings.Production.json中配置,分别为LogLevel.Debug和LogLevel.Error。可多次调用 ConfigureLogging。
1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 2. WebHost.CreateDefaultBuilder(args) 3. .ConfigureLogging(logging => 4. { 5. logging.SetMinimumLevel(LogLevel.Warning); 6. });
●ConfigureKestrel:调用ConfigureKestrel来重写CreateDefaultBuilder在配置Kestrel时建立的30,000,000字节默认Limits.MaxRequestBodySize:
1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 2. WebHost.CreateDefaultBuilder(args) 3. .ConfigureKestrel((context, options) => 4. { 5. options.Limits.MaxRequestBodySize = ; 6. });
设置主机时,可以提供配置和ConfigureServices方法。如果指定Startup类,必须定义Configure方法。
3.主机配置值
WebHostBuilder依赖于以下的方法设置主机配置值:
●主机生成器配置,其中包括格式ASPNETCORE_{configurationKey}的环境变量。例如 ASPNETCORE_ENVIRONMENT。
●UseContentRoot和UseConfiguration等扩展。
●UseSetting和关联键。使用UseSetting设置值时,该值设置为无论何种类型的字符串。
3.1应用程序键(名称)
在主机构造期间调用UseStartup或Configure时,会自动设置 IHostingEnvironment.ApplicationName属性。该值设置为包含应用入口点的程序集的名称。要显式设置值,请使用WebHostDefaults.ApplicationKey(环境变量:ASPNETCORE_APPLICATIONNAME):
1. public void Configure(IApplicationBuilder app, IHostingEnvironment env) 2. { 3. //应用程序默认名称为:CoreWeb (也就是项目名称) 4. string an = env.ApplicationName; 5. ...} 6. public static IWebHostBuilder CreateWebHostBuilder(string[] args) => 7. WebHost.CreateDefaultBuilder(args).UseStartup<Startup>() 8. .UseSetting(WebHostDefaults.ApplicationKey, "CoreWeb");
3.2捕获启动错误
此设置控制启动错误的捕获。当false时,启动期间出错导致主机退出。当true时,主机在启动期间捕获异常并尝试启动服务器。(环境变量:ASPNETCORE_CAPTURESTARTUPERRORS)
1. WebHost.CreateDefaultBuilder(args) 2. .CaptureStartupErrors(true)
3.3内容根
此设置确定ASP.NET Core开始搜索内容文件,如MVC视图等。内容根也用作Web根设置的基路径。如果路径不存在,主机将无法启动。(环境变量:ASPNETCORE_CONTENTROOT)
1. WebHost.CreateDefaultBuilder(args) 2. .UseContentRoot("c:\\<content-root>")
3.4详细错误
确定是否应捕获详细错误。启用(或当环境设置为Development)时,应用捕获详细的异常。(环境变量:ASPNETCORE_DETAILEDERRORS)
1. WebHost.CreateDefaultBuilder(args) 2. .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
3.5环境
设置应用程序的环境。环境可以设置为任何值。框架定义的值包括Development、Staging和Production。值不区分大小写。默认情况下,从ASPNETCORE_ENVIRONMENT环境变量读取环境。使用Visual Studio时,可能会在launchSettings.json文件中设置环境变量。有关于环境详情信息,可以移步到Core系列第10章节有参阅。(环境变量:ASPNETCORE_ENVIRONMENT)
1. WebHost.CreateDefaultBuilder(args) 2. .UseEnvironment(EnvironmentName.Development)
3.6HTTPS端口
设置HTTPS重定向端口。用于强制实施HTTPS。(环境变量:ASPNETCORE_HTTPS_PORT)
1. WebHost.CreateDefaultBuilder(args) 2. .UseSetting(")
3.7服务器(Kestrel) URL
指示IP地址或主机地址,其中包含服务器应针对请求侦听的端口和协议。设置为服务器应响应的以分号分隔 (;) 的URL前缀列表。例如 http://localhost:123。使用“”指示服务器应针对请求侦听的使用特定端口和协议(例如 http://:5000)的IP地址或主机名。协议(http://或https://)必须包含每个URL。不同的服务器支持的格式有所不同。(环境变量:ASPNETCORE_URLS)
1. WebHost.CreateDefaultBuilder(args)
2. .UseUrls("https://*:5000;https://localhost:5001;https://hostname:5002")


4.重写配置
使用配置可以配置Web主机。在下面的示例中,主机配置是根据需要在hostsettings.json文件中指定。命令行参数可能会重写从hostsettings.json文件加载的任何配置。生成的配置(在config中)用于通过UseConfiguration配置主机。
新建一个hostsettings.json文件,内容如下:
1. {
2. "urls": "https://*:5005"
3. }
1. public static IWebHostBuilder CreateWebHostBuilder(string[] args) 2. { 3. //IConfigurationBuilder的配置主机 4. var config = new ConfigurationBuilder() 5. .SetBasePath(Directory.GetCurrentDirectory()) 6. //主机配置在hostsettings.json文件中指定 7. .AddJsonFile("hostsettings.json", optional: true) 8. //输入的命令行参数可能会重写从hostsettings.json文件加载的任何配置 9. .AddCommandLine(args) 10. .Build(); 12. return WebHost.CreateDefaultBuilder(args) 13. .UseUrls("https://*:5001") 14. .UseConfiguration(config) 15. .Configure(app => 16. { 17. //生成的配置委托函数 18. app.Run(context => 19. context.Response.WriteAsync("Hello, World!")); 20. }); 21. }
上述代码描述意思是若要指定在特定的URL上运行的主机,所需的值可以在执行dotnet运行时从命令提示符传入。命令行参数重写hostsettings.json文件中的urls值,且服务器侦听端口8080:
1. dotnet run --urls "http://*:8080"
主机启动时,先用hostsettings.json config重写UseUrls提供的urls参数配置,然后再用命令行参数config重写hostsettings.json config的urls参数配置。
5.管理主机
管理主题启动方式有Run和Start两种。Run方法启动Web应用程序并阻止调用线程,直到关闭主机。Start方法通过调用自身以非阻止方式运行主机。
1. //Run 2. CreateWebHostBuilder(args).Build().Run();
1. //Start:非阻止方式,所有必须加上ReadLine 2. CreateWebHostBuilder(args).Build().Start(); 3. Console.ReadLine();
6.IHostingEnvironment接口
IHostingEnvironment接口提供有关应用的Web承载环境的信息。使用构造函数注入获取 IHostingEnvironment以使用其属性和扩展方法:
1. //示例1: 2. public class CustomFileReader 3. { 4. private readonly IHostingEnvironment _env; 6. public CustomFileReader(IHostingEnvironment env) 7. { 8. _env = env; 9. } 10. public string ReadFile(string filePath) 11. { 12. var fileProvider = _env.WebRootFileProvider; 13. // Process the file here 14. } 15. }
可以用于在启动时基于环境配置应用程序或者将IHostingEnvironment注入到Startup构造函数,用于ConfigureServices:
1. //示例2: 2. public class Startup 3. { 4. public Startup(IHostingEnvironment env) 5. { 6. HostingEnvironment = env; 7. } 8. public IHostingEnvironment HostingEnvironment { get; } 9. public void ConfigureServices(IServiceCollection services) 10. { 11. if (HostingEnvironment.IsDevelopment()) 12. { 13. // Development configuration 14. } 15. else 16. { 17. // Staging/Production configuration 18. } 19. var contentRootPath = HostingEnvironment.ContentRootPath; 20. } 21. }
IHostingEnvironment服务还可以直接注入到Configure方法以设置处理管道:
1. //示例3: 2. public void Configure(IApplicationBuilder app, IHostingEnvironment env) 3. { 4. if (env.IsDevelopment()) 5. { 6. // In Development, use the Developer Exception Page 7. app.UseDeveloperExceptionPage(); 8. } 9. else 10. { 11. // In Staging/Production, route exceptions to /error 12. app.UseExceptionHandler("/error"); 13. } 14. var contentRootPath = env.ContentRootPath; 15. }
创建自定义中间件(要了解中间件的同学们,可以移步到第四章节学习)时可以将IHostingEnvironment 注入Invoke方法:
1. public async Task Invoke(HttpContext context, IHostingEnvironment env) 2. { 3. if (env.IsDevelopment()) 4. { 5. // Configure middleware for Development 6. } 7. else 8. { 9. // Configure middleware for Staging/Production 10. } 11. var contentRootPath = env.ContentRootPath; 12. }
7.IApplicationLifetime接口
IApplicationLifetime允许后启动和关闭活动。接口上的三个属性是用于注册Action方法(用于定义启动和关闭事件)的取消标记。
取消标记 | 触发条件
ApplicationStarted | 主机已完全启动。
ApplicationStopped | 主机正在完成正常关闭。应处理所有请求。 关闭受到阻止,直到完成此事件。
ApplicationStopping | 主机正在执行正常关闭。仍在处理请求。关闭受到阻止,直到完成此事件。
1. public class Startup 2. { 3. public void Configure(IApplicationBuilder app, IApplicationLifetime appLifetime) 4. { 5. appLifetime.ApplicationStarted.Register(OnStarted); 6. appLifetime.ApplicationStopping.Register(OnStopping); 7. appLifetime.ApplicationStopped.Register(OnStopped); 8. Console.CancelKeyPress += (sender, eventArgs) => 9. { 10. appLifetime.StopApplication(); 11. // Don't terminate the process immediately, wait for the Main thread to exit gracefully. 12. eventArgs.Cancel = true; 13. }; 14. } 15. private void OnStarted() 16. { 17. // Perform post-startup activities here 18. } 19. private void OnStopping() 20. { 21. // Perform on-stopping activities here 22. } 23. private void OnStopped() 24. { 25. // Perform post-stopped activities here 26. } 27. }
StopApplication是请求应用终止的意思。以下类在调用类的Shutdown方法时使用StopApplication正常关闭应用:
1. public class MyClass 2. { 3. private readonly IApplicationLifetime _appLifetime; 4. public MyClass(IApplicationLifetime appLifetime) 5. { 6. _appLifetime = appLifetime; 7. } 8. public void Shutdown() 9. { 10. _appLifetime.StopApplication(); 11. } 12. }
8.作用域验证
如果应用环境为“开发(Development)”,则CreateDefaultBuilder将ServiceProviderOptions.ValidateScopes设为true。若将ValidateScopes设为true,默认服务提供应用程序会执行检查来验证以下内容:
●作用域服务不能直接或间接地从根服务提供者解析。
●作用域服务不会直接或间接地注入到单例中(服务的生命周期)。
若要始终验证作用域(包括在生命周期环境中验证),请使用主机生成器上的 UseDefaultServiceProvider配置ServiceProviderOptions:
1. WebHost.CreateDefaultBuilder(args) 2. .UseDefaultServiceProvider((context, options) => { 3. options.ValidateScopes = true; 4. })
作者:小宇宙_fly
链接:https://www.jianshu.com/p/d7d1b471e80f
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。