ASP.NET Core 中的应用程序启动代码
Posted
技术标签:
【中文标题】ASP.NET Core 中的应用程序启动代码【英文标题】:Application startup code in ASP.NET Core 【发布时间】:2016-12-27 02:21:16 【问题描述】:阅读documentation for ASP.NET Core,为启动选择了两种方法:Configure 和 ConfigureServices。
这些似乎都不是放置我想在启动时运行的自定义代码的好地方。也许我想在我的数据库中添加一个自定义字段(如果它不存在)、检查特定文件、将一些数据植入我的数据库等。我想在应用程序启动时运行一次的代码。
是否有首选/推荐的方法来执行此操作?
【问题讨论】:
添加此评论,因为我觉得它有助于保持 Startup.cs 文件干净,以获得已接受的解决方案:odetocode.com/blogs/scott/archive/2016/08/30/… 我知道这是在 2016 年提出的,但同样的问题在 2018 年仍然存在,您应该考虑我提出的观点并重新考虑接受的答案。 【参考方案1】:此类自定义代码在启动时基本上有两个入口点。
1.) Main
方法
作为一个 ASP.NET Core 应用程序有很好的旧 Main
方法作为入口点,您可以在 ASP.NET Core 启动内容之前放置代码,例如
public class Program
public static void Main(string[] args)
// call custom startup logic here
AppInitializer.Startup();
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
2.) 使用您的 Startup
类
正如您在问题中所述,Configure
和 ConfigureServices
是您自定义代码的好地方。
我更喜欢Startup
类。从运行时的角度来看,调用是在启动时调用还是在 host.Run()
调用之前的其他地方调用都没有关系。但从习惯于 ASP.NET 框架的程序员的角度来看,他首先寻找这种逻辑将是Startup.cs
文件。所有示例和模板都将身份、实体框架初始化等逻辑放在那里。因此,作为惯例,我建议将初始化的东西放在那里。
【讨论】:
Startup
类还提供了内置依赖注入容器IServiceProvider
通过IApplicationBuilder.ApplicationServices
属性在ConfigureServices
中可用的好处。
OP 说“这些似乎都不是放置自定义代码的好地方”,并不是说它们是一个好地方。【参考方案2】:
我同意 OP。
我的场景是我想向服务注册表注册一个微服务,但在微服务运行之前无法知道端点是什么。
我觉得 Configure 和 ConfigureServices 方法都不理想,因为它们都不是为了执行这种处理而设计的。
另一种情况是想要预热缓存,这也是我们可能想要做的事情。
接受的答案有几种选择:
创建另一个在您的网站之外执行更新的应用程序,例如部署工具,它在启动网站之前以编程方式应用数据库更新
在您的 Startup 类中,使用静态构造函数确保网站已准备好启动
更新
在我看来,最好的做法是像这样使用 IApplicationLifetime 接口:
public class Startup
public void Configure(IApplicationLifetime lifetime)
lifetime.ApplicationStarted.Register(OnApplicationStarted);
public void OnApplicationStarted()
// Carry out your initialisation.
【讨论】:
我发现一个请求处理已经开始了(它已经开始执行一个中间件),而 OnApplicationStarted 方法还没有完成。就我而言,它正在启动事务,而数据库尚未更新。 ApplicationStarted 文档还说:“在应用程序主机完全启动并即将等待正常关闭时触发。”这并不意味着在请求处理开始之前它不是一些初始化东西的地方。 请注意,IApplicationLifetime 在 .NET 3.x 中已弃用,新接口现在称为:IHostApplicationLifetime【参考方案3】:这可以通过创建一个IHostedService
实现并在您的启动类中使用IServiceCollection.AddHostedService<>()
in ConfigureServices()
注册它来完成。
示例
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
public class MyInitializer : IHostedService
public Task StartAsync(CancellationToken cancellationToken)
// Do your startup work here
return Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken)
// We have to implement this method too, because it is in the interface
return Task.CompletedTask;
using Microsoft.Extensions.DependencyInjection;
public class Startup
public void ConfigureServices(IServiceCollection services)
services.AddHostedService<MyInitializer>();
注意事项
在您的代码完成执行之前,不会启动主应用程序。 构造函数依赖注入可用于IHostedService
实现。
我可以推荐这篇博文了解更多信息,以及如何使用异步的示例:https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/
有关更多背景阅读,请参阅此讨论:https://github.com/dotnet/aspnetcore/issues/10137
【讨论】:
以上是关于ASP.NET Core 中的应用程序启动代码的主要内容,如果未能解决你的问题,请参考以下文章
如何从 Asp.NET Core 3.1 启动类访问 launchSettings.json 中的 `applicationUrl` 属性?
HTTP 错误 500.30 - ASP.NET Core 2.2 中的 ANCM 进程内启动失败错误
HTTP 错误 500.30 - ASP.NET Core 5 应用程序无法启动