ASP.NET Core Web 主机
注意
此版本不是本文的最新版本。 对于当前版本,请参阅此文的 .NET 8 版本。
警告
此版本的 ASP.NET Core 不再受支持。 有关详细信息,请参阅 .NET 和 .NET Core 支持策略。 对于当前版本,请参阅此文的 .NET 8 版本。
ASP.NET Core 应用配置和启动“主机”。 主机负责应用程序启动和生存期管理。 至少,主机配置服务器和请求处理管道。 主机还可以设置日志记录、依赖关系注入和配置。
本文介绍了只适用于实现后向兼容性的 Web 主机。 ASP.NET Core 模板会创建 WebApplicationBuilder 和 WebApplication,建议将它们用于 Web 应用。 有关 WebApplicationBuilder
和 WebApplication
的详细信息,请参阅从 ASP.NET Core 5.0 迁移到 6.0
设置主机
创建使用 IWebHostBuilder 实例的主机。 通常在应用的入口点来执行 Program.cs
文件中的 Main
方法。 典型应用调用 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>();
}
调用 CreateDefaultBuilder
的代码位于名为 CreateWebHostBuilder
的方法中,这让它区分于 Main
中对生成器对象调用 Run
的代码。 如果使用 Entity Framework Core 工具,必须有这种区分。 这些工具希望找到 CreateWebHostBuilder
方法,可以在设计时调用此方法来配置主机,而无需运行应用。 一种替代方法是实现 IDesignTimeDbContextFactory
。 有关详细信息,请参阅设计时 DbContext 创建。
CreateDefaultBuilder
执行下列任务:
- 使用应用的托管配置提供程序将 Kestrel 服务器配置为 Web 服务器。 有关 Kestrel 服务器的默认选项,请参阅Kestrel。
- 将内容根目录设置为由 Directory.GetCurrentDirectory 返回的路径。
- 通过以下对象加载主机配置:
- 前缀为
ASPNETCORE_
的环境变量(例如,ASPNETCORE_ENVIRONMENT
)。 - 命令行参数。
- 前缀为
- 按以下顺序加载应用配置:
appsettings.json
。appsettings.{Environment}.json
。- 应用在使用入口程序集的
Development
环境中运行时的用户机密。 - 环境变量。
- 命令行参数。
- 配置控制台和调试输出的日志记录。 日志记录包含
appsettings.json
或appsettings.{Environment}.json
文件的日志记录配置部分中指定的日志筛选规则。 - 使用 ASP.NET Core 模块在 IIS 后面运行时,
CreateDefaultBuilder
会启用 IIS 集成,这会配置应用的基址和端口。 IIS 集成还配置应用以捕获启动错误。 有关 IIS 默认选项,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core。 - 如果应用环境为“开发”,请将 ServiceProviderOptions.ValidateScopes 设为
true
。 有关详细信息,请参阅作用域验证。
ConfigureAppConfiguration、ConfigureLogging 以及 IWebHostBuilder 的其他方法和扩展方法可重写和增强 CreateDefaultBuilder
定义的配置。 下面是一些示例:
ConfigureAppConfiguration 用于为应用指定其他
IConfiguration
。 下面的ConfigureAppConfiguration
调用添加委托,以在appsettings.xml
文件中添加应用配置。 可多次调用ConfigureAppConfiguration
。 请注意,此配置不适用于主机(例如,服务器 URL 或环境)。 请参阅主机配置值部分。WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); }) ...
下面的
ConfigureLogging
调用添加委托,以将最小日志记录级别 (SetMinimumLevel) 配置为 LogLevel.Warning。 此设置将重写appsettings.Development.json
中的设置 (LogLevel.Debug
) 和由CreateDefaultBuilder
配置的appsettings.Production.json
中的设置 (LogLevel.Error
)。 可多次调用ConfigureLogging
。WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); }) ...
下面调用
ConfigureKestrel
来重写CreateDefaultBuilder
在配置 Kestrel 时建立的 30,000,000 字节默认 Limits.MaxRequestBodySize:WebHost.CreateDefaultBuilder(args) .ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 20000000; });
内容根 确定主机搜索内容文件(如 MVC 视图文件)的位置。 应用从项目的根文件夹启动时,会将项目的根文件夹用作内容根。 这是 Visual Studio 和 dotnet new 模板中使用的默认值。
有关应用配置的详细信息,请参阅 ASP.NET Core 中的配置。
注意
作为使用静态 CreateDefaultBuilder
方法的替代方法,从 WebHostBuilder 创建主机是一种受 ASP.NET Core 2.x 支持的方法。
设置主机时,可以提供Configure和 ConfigureServices 方法。 如果指定 Startup
类,必须定义 Configure
方法。 有关详细信息,请参阅 ASP.NET Core 中的应用启动。 多次调用 ConfigureServices
将追加到另一个。 多次调用 WebHostBuilder
上的 Configure
或 UseStartup
将替换以前的设置。
主机配置值
WebHostBuilder 依赖于以下的方法设置主机配置值:
- 主机生成器配置,其中包括格式
ASPNETCORE_{configurationKey}
的环境变量。 例如ASPNETCORE_ENVIRONMENT
。 - UseContentRoot 和 UseConfiguration 等扩展(请参阅重写配置部分)。
- UseSetting 和关联的键。 使用
UseSetting
设置值时,该值设置为无论何种类型的字符串。
主机使用任何一个选项设置上一个值。 有关详细信息,请参阅下一部分中的重写配置。
应用程序键(名称)
在主机构造期间调用 UseStartup 或 Configure 时,会自动设置 IWebHostEnvironment.ApplicationName
属性。 该值设置为包含应用入口点的程序集的名称。 要显式设置值,请使用 WebHostDefaults.ApplicationKey:
密钥:applicationName
类型:string
默认值:包含应用入口点的程序集的名称。
设置使用:UseSetting
环境变量:ASPNETCORE_APPLICATIONNAME
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
捕获启动错误
此设置控制启动错误的捕获。
键:captureStartupErrors
类型:布尔型(true
或 1
)
默认值:默认为 ,除非应用使用 Kestrel 在 IIS 后方运行,其中默认值是 true
。
设置使用:CaptureStartupErrors
环境变量:ASPNETCORE_CAPTURESTARTUPERRORS
当 false
时,启动期间出错导致主机退出。 当 true
时,主机在启动期间捕获异常并尝试启动服务器。
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
内容根
此设置确定 ASP.NET Core 开始搜索内容文件。
键:contentRoot
类型:string
默认:默认为应用程序集所在的文件夹。
设置使用:UseContentRoot
环境变量:ASPNETCORE_CONTENTROOT
内容根目录也用作 Web 根目录的基路径。 如果内容根路径不存在,主机将无法启动。
WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")
有关详情,请参阅:
详细错误
确定是否应捕获详细错误。
键:detailedErrors
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_DETAILEDERRORS
启用(或当环境设置为 Development
)时,应用捕获详细的异常。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
环境
设置应用的环境。
键:环境
类型:string
默认:生产
设置使用:UseEnvironment
环境变量:ASPNETCORE_ENVIRONMENT
可将环境设置为任何值。 框架定义的值包括 Development
Staging
和 Production
。 值不区分大小写。 默认情况下,从 ASPNETCORE_ENVIRONMENT
环境变量读取环境。 使用 Visual Studio 时,可在 launchSettings.json
文件中设置环境变量。 有关详细信息,请参阅在 ASP.NET Core 中使用多个环境。
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
承载启动程序集
设置应用的承载启动程序集。
键:hostingStartupAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
承载启动程序集的以分号分隔的字符串在启动时加载。
虽然配置值默认为空字符串,但是承载启动程序集会始终包含应用的程序集。 提供承载启动程序集时,当应用在启动过程中生成其公用服务时将它们添加到应用的程序集加载。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
HTTPS 端口
如果收到非 HTTPS 连接,请将 HTTPS 端口设置为重定向。 用于强制实施 HTTPS。 此设置不会导致服务器侦听指定的端口。 也就是说,可能会意外将请求重定向到未使用的端口。
密钥:https_port
类型:string
默认:未设置默认值。
设置使用:UseSetting
环境变量:ASPNETCORE_HTTPS_PORT
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")
HTTPS 端口
设置用于侦听 HTTPS 连接的端口。
密钥:https_ports 类型:字符串
默认:未设置默认值。
设置使用:UseSetting
环境变量:ASPNETCORE_HTTPS_PORTS
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_ports", "8080")
承载启动排除程序集
承载启动程序集的以分号分隔的字符串在启动时排除。
键:hostingStartupExcludeAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
首选承载 URL
指示主机是否应该侦听使用 WebHostBuilder
配置的 URL,而不是使用 IServer
实现配置的 URL。
键:preferHostingUrls
类型:布尔型(true
或 1
)
默认值:false
设置使用:PreferHostingUrls
环境变量:ASPNETCORE_PREFERHOSTINGURLS
WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(true)
阻止承载启动
阻止承载启动程序集自动加载,包括应用的程序集所配置的承载启动程序集。 有关详细信息,请参阅在 ASP.NET Core 中使用托管启动程序集。
键:preventHostingStartup
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_PREVENTHOSTINGSTARTUP
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
服务器 URL
指示 IP 地址或主机地址,其中包含服务器应针对请求侦听的端口和协议。
键:urls
类型:string
默认:http://localhost:5000
设置使用:UseUrls
环境变量: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 具有自己的终结点配置 API。 有关详细信息,请参阅为 ASP.NET Core Kestrel Web 服务器配置终结点。
关闭超时
指定等待 Web 主机关闭的时长。
键:shutdownTimeoutSeconds
类型:int
默认:5
设置使用:UseShutdownTimeout
环境变量:ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
虽然键使用 UseSetting
接受 int(例如 .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")
),但是 UseShutdownTimeout 扩展方法采用 TimeSpan。
在超时时间段中,托管:
- 触发 IApplicationLifetime.ApplicationStopping。
- 尝试停止托管服务,对服务停止失败的任何错误进行日志记录。
如果在所有托管服务停止之前就达到了超时时间,则会在应用关闭时会终止剩余的所有活动的服务。 即使没有完成处理工作,服务也会停止。 如果停止服务需要额外的时间,请增加超时时间。
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
启动程序集
确定要在其中搜索 Startup
类的程序集。
键:startupAssembly
类型:string
默认:应用的程序集
设置使用:UseStartup
环境变量:ASPNETCORE_STARTUPASSEMBLY
按名称(string
)或类型(TStartup
)的程序集可以引用。 如果调用多个 UseStartup
方法,优先选择最后一个方法。
WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
Web 根
设置应用的静态资产的相对路径。
键:webroot
类型:string
默认:默认值为 wwwroot
。 {content root}/wwwroot 的路径必须存在。 如果该路径不存在,则使用无操作文件提供程序。
设置使用:UseWebRoot
环境变量:ASPNETCORE_WEBROOT
WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")
有关详情,请参阅:
重写配置
使用配置可以配置 Web 主机。 在以下示例中,在 hostsettings.json
文件中指定主机配置(可选)。 从 hostsettings.json
文件加载的任何配置可能会由命令行参数替代。 生成的配置(在 config
中)用于通过 UseConfiguration 配置主机。 IWebHostBuilder
配置会添加到应用配置中,但反之不亦然 ConfigureAppConfiguration
不影响 IWebHostBuilder
配置。
首先用 hostsettings.json
配置替代 UseUrls
提供的配置,然后是命令行参数配置:
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
中的密钥复制到主机生成器配置中。 因此,JSON、INI 和 XML 设置文件的设置 reloadOnChange: true
没有任何影响。
若要指定在特定的 URL 上运行的主机,所需的值可以在执行 dotnet 运行时从命令提示符传入。 命令行参数替代 hostsettings.json
文件中的 urls
值,且服务器侦听端口 8080:
dotnet run --urls "http://*:8080"
管理主机
运行
Run
方法启动 Web 应用并阻止调用线程,直到关闭主机:
host.Run();
Start
通过调用 Start
方法以非阻止方式运行主机:
using (host)
{
host.Start();
Console.ReadLine();
}
如果 URL 列表传递给 Start
方法,该列表侦听指定的 URL:
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
默认值初始化并启动新的主机。 这些方法在没有控制台输出的情况下启动服务器,并使用 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
消息并等待 keypress 退出。
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> routeBuilder)
使用 IRouteBuilder
的实例 (Microsoft.AspNetCore.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();
}
该示例中使用以下浏览器请求:
请求 | 响应 |
---|---|
http://localhost:5000/hello/Martin |
Hello, Martin! |
http://localhost:5000/buenosdias/Catrina |
Buenos dias, Catrina! |
http://localhost:5000/throw/ooops! |
使用“ooops!”字符串引发异常 |
http://localhost:5000/throw |
使用“Uh oh!”字符串引发异常 |
http://localhost:5000/Sante/Kevin |
Sante, Kevin! |
http://localhost:5000 |
Hello World! |
WaitForShutdown
受到阻止,直到发出中断(Ctrl-C/SIGINT 或 SIGTERM)。 应用显示 Console.WriteLine
消息并等待 keypress 退出。
Start(string url, Action<IRouteBuilder> routeBuilder)
使用 URL 和 IRouteBuilder
实例:
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
消息并等待 keypress 退出。
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<IApplicationBuilder> app) 相同的结果,除非应用在 http://localhost:8080
上响应。
IWebHostEnvironment 接口
IWebHostEnvironment
接口提供有关应用的 Web 托管环境的信息。 使用构造函数注入获取 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
}
}
基于约定的方法可以用于在启动时基于环境配置应用。 或者,将 IWebHostEnvironment
注入到 Startup
构造函数用于 ConfigureServices
:
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 environmentName)
方法。 有关详细信息,请参阅在 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;
}
创建自定义中间件时可以将 IWebHostEnvironment
注入 Invoke
方法:
public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}
var contentRootPath = env.ContentRootPath;
}
IHostApplicationLifetime 接口
IHostApplicationLifetime
允许后启动和关闭活动。 接口上的三个属性是用于注册 Action
方法(用于定义启动和关闭事件)的取消标记。
取消标记 | 触发条件… |
---|---|
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
请求终止应用。 以下类在调用类的 Shutdown
方法时使用 StopApplication
正常关闭应用:
public class MyClass
{
private readonly IHostApplicationLifetime _appLifetime;
public MyClass(IHostApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
作用域验证
如果应用的环境为“开发”,CreateDefaultBuilder 将 ServiceProviderOptions.ValidateScopes 设置为 true
。
若将 ValidateScopes
设为 true
,默认服务提供程序会执行检查来验证以下内容:
- 没有从根服务提供程序直接或间接解析到有作用域的服务。
- 未将有作用域的服务直接或间接注入到单一实例。
调用 BuildServiceProvider 时创建根服务提供程序。 在启动提供程序和应用时,根服务提供程序的生存期对应于应用/服务的生存期,并在关闭应用时释放。
有作用域的服务由创建它们的容器释放。 如果作用域服务创建于根容器,则该服务的生存期会实际上提升至单一实例,因为根容器只会在应用/服务关闭时将其释放。 验证服务作用域,将在调用 BuildServiceProvider
时收集这类情况。
若要始终验证作用域(包括在生存环境中验证),请使用主机生成器上的 UseDefaultServiceProvider 配置 ServiceProviderOptions:
WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})
其他资源
ASP.NET Core 应用配置和启动“主机”。 主机负责应用程序启动和生存期管理。 至少,主机配置服务器和请求处理管道。 主机还可以设置日志记录、依赖关系注入和配置。
本文介绍了只适用于实现后向兼容性的 Web 主机。 ASP.NET Core 模板会创建一个 .NET 通用主机,建议将这个主机用于所有应用类型。
设置主机
创建使用 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>();
}
调用 CreateDefaultBuilder
的代码位于名为 CreateWebHostBuilder
的方法中,这让它区分于 Main
中对生成器对象调用 Run
的代码。 如果使用 Entity Framework Core 工具,必须有这种区分。 这些工具希望找到 CreateWebHostBuilder
方法,可以在设计时调用此方法来配置主机,而无需运行应用。 一种替代方法是实现 IDesignTimeDbContextFactory
。 有关详细信息,请参阅设计时 DbContext 创建。
CreateDefaultBuilder
执行下列任务:
- 使用应用的托管配置提供程序将 Kestrel 服务器配置为 Web 服务器。 有关 Kestrel 服务器的默认选项,请参阅Kestrel。
- 将内容根目录设置为由 Directory.GetCurrentDirectory 返回的路径。
- 通过以下对象加载主机配置:
- 前缀为
ASPNETCORE_
的环境变量(例如,ASPNETCORE_ENVIRONMENT
)。 - 命令行参数。
- 前缀为
- 按以下顺序加载应用配置:
appsettings.json
。appsettings.{Environment}.json
。- 应用在使用入口程序集的
Development
环境中运行时的用户机密。 - 环境变量。
- 命令行参数。
- 配置控制台和调试输出的日志记录。 日志记录包含
appsettings.json
或appsettings.{Environment}.json
文件的日志记录配置部分中指定的日志筛选规则。 - 使用 ASP.NET Core 模块在 IIS 后面运行时,
CreateDefaultBuilder
会启用 IIS 集成,这会配置应用的基址和端口。 IIS 集成还配置应用以捕获启动错误。 有关 IIS 默认选项,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core。 - 如果应用环境为“开发”,请将 ServiceProviderOptions.ValidateScopes 设为
true
。 有关详细信息,请参阅作用域验证。
ConfigureAppConfiguration、ConfigureLogging 以及 IWebHostBuilder 的其他方法和扩展方法可重写和增强 CreateDefaultBuilder
定义的配置。 下面是一些示例:
ConfigureAppConfiguration 用于为应用指定其他
IConfiguration
。 下面的ConfigureAppConfiguration
调用添加委托,以在appsettings.xml
文件中添加应用配置。 可多次调用ConfigureAppConfiguration
。 请注意,此配置不适用于主机(例如,服务器 URL 或环境)。 请参阅主机配置值部分。WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); }) ...
下面的
ConfigureLogging
调用添加委托,以将最小日志记录级别 (SetMinimumLevel) 配置为 LogLevel.Warning。 此设置将重写appsettings.Development.json
中的设置 (LogLevel.Debug
) 和由CreateDefaultBuilder
配置的appsettings.Production.json
中的设置 (LogLevel.Error
)。 可多次调用ConfigureLogging
。WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); }) ...
下面调用
ConfigureKestrel
来重写CreateDefaultBuilder
在配置 Kestrel 时建立的 30,000,000 字节默认 Limits.MaxRequestBodySize:WebHost.CreateDefaultBuilder(args) .ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 20000000; });
内容根 确定主机搜索内容文件(如 MVC 视图文件)的位置。 应用从项目的根文件夹启动时,会将项目的根文件夹用作内容根。 这是 Visual Studio 和 dotnet new 模板中使用的默认值。
有关应用配置的详细信息,请参阅 ASP.NET Core 中的配置。
注意
作为使用静态 CreateDefaultBuilder
方法的替代方法,从 WebHostBuilder 创建主机是一种受 ASP.NET Core 2.x 支持的方法。
设置主机时,可以提供Configure和 ConfigureServices 方法。 如果指定 Startup
类,必须定义 Configure
方法。 有关详细信息,请参阅 ASP.NET Core 中的应用启动。 多次调用 ConfigureServices
将追加到另一个。 多次调用 WebHostBuilder
上的 Configure
或 UseStartup
将替换以前的设置。
主机配置值
WebHostBuilder 依赖于以下的方法设置主机配置值:
- 主机生成器配置,其中包括格式
ASPNETCORE_{configurationKey}
的环境变量。 例如ASPNETCORE_ENVIRONMENT
。 - UseContentRoot 和 UseConfiguration 等扩展(请参阅重写配置部分)。
- UseSetting 和关联的键。 使用
UseSetting
设置值时,该值设置为无论何种类型的字符串。
主机使用任何一个选项设置上一个值。 有关详细信息,请参阅下一部分中的重写配置。
应用程序键(名称)
在主机构造期间调用 UseStartup 或 Configure 时,会自动设置 IWebHostEnvironment.ApplicationName
属性。 该值设置为包含应用入口点的程序集的名称。 要显式设置值,请使用 WebHostDefaults.ApplicationKey:
密钥:applicationName
类型:string
默认值:包含应用入口点的程序集的名称。
设置使用:UseSetting
环境变量:ASPNETCORE_APPLICATIONNAME
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
捕获启动错误
此设置控制启动错误的捕获。
键:captureStartupErrors
类型:布尔型(true
或 1
)
默认值:默认为 ,除非应用使用 Kestrel 在 IIS 后方运行,其中默认值是 true
。
设置使用:CaptureStartupErrors
环境变量:ASPNETCORE_CAPTURESTARTUPERRORS
当 false
时,启动期间出错导致主机退出。 当 true
时,主机在启动期间捕获异常并尝试启动服务器。
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
内容根
此设置确定 ASP.NET Core 开始搜索内容文件。
键:contentRoot
类型:string
默认:默认为应用程序集所在的文件夹。
设置使用:UseContentRoot
环境变量:ASPNETCORE_CONTENTROOT
内容根目录也用作 Web 根目录的基路径。 如果内容根路径不存在,主机将无法启动。
WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")
有关详情,请参阅:
详细错误
确定是否应捕获详细错误。
键:detailedErrors
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_DETAILEDERRORS
启用(或当环境设置为 Development
)时,应用捕获详细的异常。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
环境
设置应用的环境。
键:环境
类型:string
默认:生产
设置使用:UseEnvironment
环境变量:ASPNETCORE_ENVIRONMENT
可将环境设置为任何值。 框架定义的值包括 Development
Staging
和 Production
。 值不区分大小写。 默认情况下,从 ASPNETCORE_ENVIRONMENT
环境变量读取环境。 使用 Visual Studio 时,可在 launchSettings.json
文件中设置环境变量。 有关详细信息,请参阅在 ASP.NET Core 中使用多个环境。
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
承载启动程序集
设置应用的承载启动程序集。
键:hostingStartupAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
承载启动程序集的以分号分隔的字符串在启动时加载。
虽然配置值默认为空字符串,但是承载启动程序集会始终包含应用的程序集。 提供承载启动程序集时,当应用在启动过程中生成其公用服务时将它们添加到应用的程序集加载。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
HTTPS 端口
设置 HTTPS 重定向端口。 用于强制实施 HTTPS。
密钥:https_port
类型:string
默认:未设置默认值。
设置使用:UseSetting
环境变量:ASPNETCORE_HTTPS_PORTS
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")
承载启动排除程序集
承载启动程序集的以分号分隔的字符串在启动时排除。
键:hostingStartupExcludeAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
首选承载 URL
指示主机是否应该侦听使用 WebHostBuilder
配置的 URL,而不是使用 IServer
实现配置的 URL。
键:preferHostingUrls
类型:布尔型(true
或 1
)
默认值:false
设置使用:PreferHostingUrls
环境变量:ASPNETCORE_PREFERHOSTINGURLS
WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(true)
阻止承载启动
阻止承载启动程序集自动加载,包括应用的程序集所配置的承载启动程序集。 有关详细信息,请参阅在 ASP.NET Core 中使用托管启动程序集。
键:preventHostingStartup
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_PREVENTHOSTINGSTARTUP
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
服务器 URL
指示 IP 地址或主机地址,其中包含服务器应针对请求侦听的端口和协议。
键:urls
类型:string
默认:http://localhost:5000
设置使用:UseUrls
环境变量: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 具有自己的终结点配置 API。 有关详细信息,请参阅为 ASP.NET Core Kestrel Web 服务器配置终结点。
关闭超时
指定等待 Web 主机关闭的时长。
键:shutdownTimeoutSeconds
类型:int
默认:5
设置使用:UseShutdownTimeout
环境变量:ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
虽然键使用 UseSetting
接受 int(例如 .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")
),但是 UseShutdownTimeout 扩展方法采用 TimeSpan。
在超时时间段中,托管:
- 触发 IApplicationLifetime.ApplicationStopping。
- 尝试停止托管服务,对服务停止失败的任何错误进行日志记录。
如果在所有托管服务停止之前就达到了超时时间,则会在应用关闭时会终止剩余的所有活动的服务。 即使没有完成处理工作,服务也会停止。 如果停止服务需要额外的时间,请增加超时时间。
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
启动程序集
确定要在其中搜索 Startup
类的程序集。
键:startupAssembly
类型:string
默认:应用的程序集
设置使用:UseStartup
环境变量:ASPNETCORE_STARTUPASSEMBLY
按名称(string
)或类型(TStartup
)的程序集可以引用。 如果调用多个 UseStartup
方法,优先选择最后一个方法。
WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
Web 根
设置应用的静态资产的相对路径。
键:webroot
类型:string
默认:默认值为 wwwroot
。 {content root}/wwwroot 的路径必须存在。 如果该路径不存在,则使用无操作文件提供程序。
设置使用:UseWebRoot
环境变量:ASPNETCORE_WEBROOT
WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")
有关详情,请参阅:
重写配置
使用配置可以配置 Web 主机。 在以下示例中,在 hostsettings.json
文件中指定主机配置(可选)。 从 hostsettings.json
文件加载的任何配置可能会由命令行参数替代。 生成的配置(在 config
中)用于通过 UseConfiguration 配置主机。 IWebHostBuilder
配置会添加到应用配置中,但反之不亦然 ConfigureAppConfiguration
不影响 IWebHostBuilder
配置。
首先用 hostsettings.json
配置替代 UseUrls
提供的配置,然后是命令行参数配置:
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
中的密钥复制到主机生成器配置中。 因此,JSON、INI 和 XML 设置文件的设置 reloadOnChange: true
没有任何影响。
若要指定在特定的 URL 上运行的主机,所需的值可以在执行 dotnet 运行时从命令提示符传入。 命令行参数替代 hostsettings.json
文件中的 urls
值,且服务器侦听端口 8080:
dotnet run --urls "http://*:8080"
管理主机
运行
Run
方法启动 Web 应用并阻止调用线程,直到关闭主机:
host.Run();
Start
通过调用 Start
方法以非阻止方式运行主机:
using (host)
{
host.Start();
Console.ReadLine();
}
如果 URL 列表传递给 Start
方法,该列表侦听指定的 URL:
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
默认值初始化并启动新的主机。 这些方法在没有控制台输出的情况下启动服务器,并使用 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
消息并等待 keypress 退出。
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> routeBuilder)
使用 IRouteBuilder
的实例 (Microsoft.AspNetCore.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();
}
该示例中使用以下浏览器请求:
请求 | 响应 |
---|---|
http://localhost:5000/hello/Martin |
Hello, Martin! |
http://localhost:5000/buenosdias/Catrina |
Buenos dias, Catrina! |
http://localhost:5000/throw/ooops! |
使用“ooops!”字符串引发异常 |
http://localhost:5000/throw |
使用“Uh oh!”字符串引发异常 |
http://localhost:5000/Sante/Kevin |
Sante, Kevin! |
http://localhost:5000 |
Hello World! |
WaitForShutdown
受到阻止,直到发出中断(Ctrl-C/SIGINT 或 SIGTERM)。 应用显示 Console.WriteLine
消息并等待 keypress 退出。
Start(string url, Action<IRouteBuilder> routeBuilder)
使用 URL 和 IRouteBuilder
实例:
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
消息并等待 keypress 退出。
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<IApplicationBuilder> app) 相同的结果,除非应用在 http://localhost:8080
上响应。
IWebHostEnvironment 接口
IWebHostEnvironment
接口提供有关应用的 Web 托管环境的信息。 使用构造函数注入获取 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
}
}
基于约定的方法可以用于在启动时基于环境配置应用。 或者,将 IWebHostEnvironment
注入到 Startup
构造函数用于 ConfigureServices
:
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 environmentName)
方法。 有关详细信息,请参阅在 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;
}
创建自定义中间件时可以将 IWebHostEnvironment
注入 Invoke
方法:
public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}
var contentRootPath = env.ContentRootPath;
}
IHostApplicationLifetime 接口
IHostApplicationLifetime
允许后启动和关闭活动。 接口上的三个属性是用于注册 Action
方法(用于定义启动和关闭事件)的取消标记。
取消标记 | 触发条件… |
---|---|
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
请求终止应用。 以下类在调用类的 Shutdown
方法时使用 StopApplication
正常关闭应用:
public class MyClass
{
private readonly IHostApplicationLifetime _appLifetime;
public MyClass(IHostApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
作用域验证
如果应用的环境为“开发”,CreateDefaultBuilder 将 ServiceProviderOptions.ValidateScopes 设置为 true
。
若将 ValidateScopes
设为 true
,默认服务提供程序会执行检查来验证以下内容:
- 没有从根服务提供程序直接或间接解析到有作用域的服务。
- 未将有作用域的服务直接或间接注入到单一实例。
调用 BuildServiceProvider 时创建根服务提供程序。 在启动提供程序和应用时,根服务提供程序的生存期对应于应用/服务的生存期,并在关闭应用时释放。
有作用域的服务由创建它们的容器释放。 如果作用域服务创建于根容器,则该服务的生存期会实际上提升至单一实例,因为根容器只会在应用/服务关闭时将其释放。 验证服务作用域,将在调用 BuildServiceProvider
时收集这类情况。
若要始终验证作用域(包括在生存环境中验证),请使用主机生成器上的 UseDefaultServiceProvider 配置 ServiceProviderOptions:
WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})
其他资源
ASP.NET Core 应用配置和启动“主机”。 主机负责应用程序启动和生存期管理。 至少,主机配置服务器和请求处理管道。 主机还可以设置日志记录、依赖关系注入和配置。
本文介绍了只适用于实现后向兼容性的 Web 主机。 ASP.NET Core 模板会创建一个 .NET 通用主机,建议将这个主机用于所有应用类型。
设置主机
创建使用 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>();
}
调用 CreateDefaultBuilder
的代码位于名为 CreateWebHostBuilder
的方法中,这让它区分于 Main
中对生成器对象调用 Run
的代码。 如果使用 Entity Framework Core 工具,必须有这种区分。 这些工具希望找到 CreateWebHostBuilder
方法,可以在设计时调用此方法来配置主机,而无需运行应用。 一种替代方法是实现 IDesignTimeDbContextFactory
。 有关详细信息,请参阅设计时 DbContext 创建。
CreateDefaultBuilder
执行下列任务:
- 使用应用的托管配置提供程序将 Kestrel 服务器配置为 Web 服务器。 有关 Kestrel 服务器的默认选项,请参阅 ASP.NET Core 中的 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 集成还配置应用以捕获启动错误。 有关 IIS 默认选项,请参阅使用 IIS 在 Windows 上托管 ASP.NET Core。 - 如果应用环境为“开发”,请将 ServiceProviderOptions.ValidateScopes 设为
true
。 有关详细信息,请参阅作用域验证。
ConfigureAppConfiguration、ConfigureLogging 以及 IWebHostBuilder 的其他方法和扩展方法可重写和增强 CreateDefaultBuilder
定义的配置。 下面是一些示例:
ConfigureAppConfiguration 用于为应用指定其他
IConfiguration
。 下面的ConfigureAppConfiguration
调用添加委托,以在appsettings.xml
文件中添加应用配置。 可多次调用ConfigureAppConfiguration
。 请注意,此配置不适用于主机(例如,服务器 URL 或环境)。 请参阅主机配置值部分。WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddXmlFile("appsettings.xml", optional: true, reloadOnChange: true); }) ...
下面的
ConfigureLogging
调用添加委托,以将最小日志记录级别 (SetMinimumLevel) 配置为 LogLevel.Warning。 此设置将重写appsettings.Development.json
中的设置 (LogLevel.Debug
) 和由CreateDefaultBuilder
配置的appsettings.Production.json
中的设置 (LogLevel.Error
)。 可多次调用ConfigureLogging
。WebHost.CreateDefaultBuilder(args) .ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Warning); }) ...
下面调用
ConfigureKestrel
来重写CreateDefaultBuilder
在配置 Kestrel 时建立的 30,000,000 字节默认 Limits.MaxRequestBodySize:WebHost.CreateDefaultBuilder(args) .ConfigureKestrel((context, options) => { options.Limits.MaxRequestBodySize = 20000000; });
内容根 确定主机搜索内容文件(如 MVC 视图文件)的位置。 应用从项目的根文件夹启动时,会将项目的根文件夹用作内容根。 这是 Visual Studio 和 dotnet new 模板中使用的默认值。
有关应用配置的详细信息,请参阅 ASP.NET Core 中的配置。
注意
作为使用静态 CreateDefaultBuilder
方法的替代方法,从 WebHostBuilder 创建主机是一种受 ASP.NET Core 2.x 支持的方法。
设置主机时,可以提供Configure和 ConfigureServices 方法。 如果指定 Startup
类,必须定义 Configure
方法。 有关详细信息,请参阅 ASP.NET Core 中的应用启动。 多次调用 ConfigureServices
将追加到另一个。 多次调用 WebHostBuilder
上的 Configure
或 UseStartup
将替换以前的设置。
主机配置值
WebHostBuilder 依赖于以下的方法设置主机配置值:
- 主机生成器配置,其中包括格式
ASPNETCORE_{configurationKey}
的环境变量。 例如ASPNETCORE_ENVIRONMENT
。 - UseContentRoot 和 UseConfiguration 等扩展(请参阅重写配置部分)。
- UseSetting 和关联的键。 使用
UseSetting
设置值时,该值设置为无论何种类型的字符串。
主机使用任何一个选项设置上一个值。 有关详细信息,请参阅下一部分中的重写配置。
应用程序键(名称)
在主机构造期间调用 UseStartup 或 Configure 时,会自动设置 IWebHostEnvironment.ApplicationName
属性。 该值设置为包含应用入口点的程序集的名称。 要显式设置值,请使用 WebHostDefaults.ApplicationKey:
密钥:applicationName
类型:string
默认值:包含应用入口点的程序集的名称。
设置使用:UseSetting
环境变量:ASPNETCORE_APPLICATIONNAME
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.ApplicationKey, "CustomApplicationName")
捕获启动错误
此设置控制启动错误的捕获。
键:captureStartupErrors
类型:布尔型(true
或 1
)
默认值:默认为 ,除非应用使用 Kestrel 在 IIS 后方运行,其中默认值是 true
。
设置使用:CaptureStartupErrors
环境变量:ASPNETCORE_CAPTURESTARTUPERRORS
当 false
时,启动期间出错导致主机退出。 当 true
时,主机在启动期间捕获异常并尝试启动服务器。
WebHost.CreateDefaultBuilder(args)
.CaptureStartupErrors(true)
内容根
此设置确定 ASP.NET Core 开始搜索内容文件。
键:contentRoot
类型:string
默认:默认为应用程序集所在的文件夹。
设置使用:UseContentRoot
环境变量:ASPNETCORE_CONTENTROOT
内容根目录也用作 Web 根目录的基路径。 如果内容根路径不存在,主机将无法启动。
WebHost.CreateDefaultBuilder(args)
.UseContentRoot("c:\\<content-root>")
有关详情,请参阅:
详细错误
确定是否应捕获详细错误。
键:detailedErrors
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_DETAILEDERRORS
启用(或当环境设置为 Development
)时,应用捕获详细的异常。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
环境
设置应用的环境。
键:环境
类型:string
默认:生产
设置使用:UseEnvironment
环境变量:ASPNETCORE_ENVIRONMENT
可将环境设置为任何值。 框架定义的值包括 Development
Staging
和 Production
。 值不区分大小写。 默认情况下,从 ASPNETCORE_ENVIRONMENT
环境变量读取环境。 使用 Visual Studio 时,可在 launchSettings.json
文件中设置环境变量。 有关详细信息,请参阅在 ASP.NET Core 中使用多个环境。
WebHost.CreateDefaultBuilder(args)
.UseEnvironment(EnvironmentName.Development)
承载启动程序集
设置应用的承载启动程序集。
键:hostingStartupAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
承载启动程序集的以分号分隔的字符串在启动时加载。
虽然配置值默认为空字符串,但是承载启动程序集会始终包含应用的程序集。 提供承载启动程序集时,当应用在启动过程中生成其公用服务时将它们添加到应用的程序集加载。
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "assembly1;assembly2")
HTTPS 端口
设置 HTTPS 重定向端口。 用于强制实施 HTTPS。
密钥:https_port
类型:string
默认:未设置默认值。
设置使用:UseSetting
环境变量:ASPNETCORE_HTTPS_PORTS
WebHost.CreateDefaultBuilder(args)
.UseSetting("https_port", "8080")
承载启动排除程序集
承载启动程序集的以分号分隔的字符串在启动时排除。
键:hostingStartupExcludeAssemblies
类型:string
默认:空字符串
设置使用:UseSetting
环境变量:ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "assembly1;assembly2")
首选承载 URL
指示主机是否应该侦听使用 WebHostBuilder
配置的 URL,而不是使用 IServer
实现配置的 URL。
键:preferHostingUrls
类型:布尔型(true
或 1
)
默认值:false
设置使用:PreferHostingUrls
环境变量:ASPNETCORE_PREFERHOSTINGURLS
WebHost.CreateDefaultBuilder(args)
.PreferHostingUrls(true)
阻止承载启动
阻止承载启动程序集自动加载,包括应用的程序集所配置的承载启动程序集。 有关详细信息,请参阅在 ASP.NET Core 中使用托管启动程序集。
键:preventHostingStartup
类型:布尔型(true
或 1
)
默认值:false
设置使用:UseSetting
环境变量:ASPNETCORE_PREVENTHOSTINGSTARTUP
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true")
服务器 URL
指示 IP 地址或主机地址,其中包含服务器应针对请求侦听的端口和协议。
键:urls
类型:string
默认:http://localhost:5000
设置使用:UseUrls
环境变量: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 具有自己的终结点配置 API。 有关详细信息,请参阅 ASP.NET Core 中的 Kestrel Web 服务器。
关闭超时
指定等待 Web 主机关闭的时长。
键:shutdownTimeoutSeconds
类型:int
默认:5
设置使用:UseShutdownTimeout
环境变量:ASPNETCORE_SHUTDOWNTIMEOUTSECONDS
虽然键使用 UseSetting
接受 int(例如 .UseSetting(WebHostDefaults.ShutdownTimeoutKey, "10")
),但是 UseShutdownTimeout 扩展方法采用 TimeSpan。
在超时时间段中,托管:
- 触发 IApplicationLifetime.ApplicationStopping。
- 尝试停止托管服务,对服务停止失败的任何错误进行日志记录。
如果在所有托管服务停止之前就达到了超时时间,则会在应用关闭时会终止剩余的所有活动的服务。 即使没有完成处理工作,服务也会停止。 如果停止服务需要额外的时间,请增加超时时间。
WebHost.CreateDefaultBuilder(args)
.UseShutdownTimeout(TimeSpan.FromSeconds(10))
启动程序集
确定要在其中搜索 Startup
类的程序集。
键:startupAssembly
类型:string
默认:应用的程序集
设置使用:UseStartup
环境变量:ASPNETCORE_STARTUPASSEMBLY
按名称(string
)或类型(TStartup
)的程序集可以引用。 如果调用多个 UseStartup
方法,优先选择最后一个方法。
WebHost.CreateDefaultBuilder(args)
.UseStartup("StartupAssemblyName")
WebHost.CreateDefaultBuilder(args)
.UseStartup<TStartup>()
Web 根
设置应用的静态资产的相对路径。
键:webroot
类型:string
默认:默认值为 wwwroot
。 {content root}/wwwroot 的路径必须存在。 如果该路径不存在,则使用无操作文件提供程序。
设置使用:UseWebRoot
环境变量:ASPNETCORE_WEBROOT
WebHost.CreateDefaultBuilder(args)
.UseWebRoot("public")
有关详情,请参阅:
重写配置
使用配置可以配置 Web 主机。 在以下示例中,在 hostsettings.json
文件中指定主机配置(可选)。 从 hostsettings.json
文件加载的任何配置可能会由命令行参数替代。 生成的配置(在 config
中)用于通过 UseConfiguration 配置主机。 IWebHostBuilder
配置会添加到应用配置中,但反之不亦然 ConfigureAppConfiguration
不影响 IWebHostBuilder
配置。
首先用 hostsettings.json
配置替代 UseUrls
提供的配置,然后是命令行参数配置:
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
中的密钥复制到主机生成器配置中。 因此,JSON、INI 和 XML 设置文件的设置 reloadOnChange: true
没有任何影响。
若要指定在特定的 URL 上运行的主机,所需的值可以在执行 dotnet 运行时从命令提示符传入。 命令行参数替代 hostsettings.json
文件中的 urls
值,且服务器侦听端口 8080:
dotnet run --urls "http://*:8080"
管理主机
运行
Run
方法启动 Web 应用并阻止调用线程,直到关闭主机:
host.Run();
Start
通过调用 Start
方法以非阻止方式运行主机:
using (host)
{
host.Start();
Console.ReadLine();
}
如果 URL 列表传递给 Start
方法,该列表侦听指定的 URL:
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
默认值初始化并启动新的主机。 这些方法在没有控制台输出的情况下启动服务器,并使用 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
消息并等待 keypress 退出。
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> routeBuilder)
使用 IRouteBuilder
的实例 (Microsoft.AspNetCore.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();
}
该示例中使用以下浏览器请求:
请求 | 响应 |
---|---|
http://localhost:5000/hello/Martin |
Hello, Martin! |
http://localhost:5000/buenosdias/Catrina |
Buenos dias, Catrina! |
http://localhost:5000/throw/ooops! |
使用“ooops!”字符串引发异常 |
http://localhost:5000/throw |
使用“Uh oh!”字符串引发异常 |
http://localhost:5000/Sante/Kevin |
Sante, Kevin! |
http://localhost:5000 |
Hello World! |
WaitForShutdown
受到阻止,直到发出中断(Ctrl-C/SIGINT 或 SIGTERM)。 应用显示 Console.WriteLine
消息并等待 keypress 退出。
Start(string url, Action<IRouteBuilder> routeBuilder)
使用 URL 和 IRouteBuilder
实例:
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
消息并等待 keypress 退出。
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<IApplicationBuilder> app) 相同的结果,除非应用在 http://localhost:8080
上响应。
IWebHostEnvironment 接口
IWebHostEnvironment
接口提供有关应用的 Web 托管环境的信息。 使用构造函数注入获取 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
}
}
基于约定的方法可以用于在启动时基于环境配置应用。 或者,将 IWebHostEnvironment
注入到 Startup
构造函数用于 ConfigureServices
:
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 environmentName)
方法。 有关详细信息,请参阅在 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;
}
创建自定义中间件时可以将 IWebHostEnvironment
注入 Invoke
方法:
public async Task Invoke(HttpContext context, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
// Configure middleware for Development
}
else
{
// Configure middleware for Staging/Production
}
var contentRootPath = env.ContentRootPath;
}
IHostApplicationLifetime 接口
IHostApplicationLifetime
允许后启动和关闭活动。 接口上的三个属性是用于注册 Action
方法(用于定义启动和关闭事件)的取消标记。
取消标记 | 触发条件… |
---|---|
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
请求终止应用。 以下类在调用类的 Shutdown
方法时使用 StopApplication
正常关闭应用:
public class MyClass
{
private readonly IHostApplicationLifetime _appLifetime;
public MyClass(IHostApplicationLifetime appLifetime)
{
_appLifetime = appLifetime;
}
public void Shutdown()
{
_appLifetime.StopApplication();
}
}
作用域验证
如果应用的环境为“开发”,CreateDefaultBuilder 将 ServiceProviderOptions.ValidateScopes 设置为 true
。
若将 ValidateScopes
设为 true
,默认服务提供程序会执行检查来验证以下内容:
- 没有从根服务提供程序直接或间接解析到有作用域的服务。
- 未将有作用域的服务直接或间接注入到单一实例。
调用 BuildServiceProvider 时创建根服务提供程序。 在启动提供程序和应用时,根服务提供程序的生存期对应于应用/服务的生存期,并在关闭应用时释放。
有作用域的服务由创建它们的容器释放。 如果作用域服务创建于根容器,则该服务的生存期会实际上提升至单一实例,因为根容器只会在应用/服务关闭时将其释放。 验证服务作用域,将在调用 BuildServiceProvider
时收集这类情况。
若要始终验证作用域(包括在生存环境中验证),请使用主机生成器上的 UseDefaultServiceProvider 配置 ServiceProviderOptions:
WebHost.CreateDefaultBuilder(args)
.UseDefaultServiceProvider((context, options) => {
options.ValidateScopes = true;
})