ASP.NET 核心中的应用程序启动代码
Application startup code in ASP.NET Core
仔细阅读 documentation for ASP.NET Core,有两种启动方法:Configure 和 ConfigureServices。
这些似乎都不是放置我想要在启动时 运行 的自定义代码的好地方。也许我想在我的数据库中添加一个自定义字段(如果它不存在)、检查特定文件、将一些数据植入我的数据库等。我想 运行 一次的代码,就在应用程序启动时。
是否有 preferred/recommended 方法来执行此操作?
在启动时,此类自定义代码基本上有两个入口点。
1.) Main
方法
作为一个 ASP.NET 核心应用程序有很好的旧 Main
方法作为入口点,你可以将代码放在 ASP.NET 核心启动的东西之前,比如
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
class
正如您在问题中所述,Configure
和 ConfigureServices
是放置自定义代码的好地方。
我更喜欢 Startup
class。从运行时的角度来看,调用是在启动时调用还是在 host.Run()
调用之前的其他地方调用并不重要。但是从一个习惯于 ASP.NET 框架的程序员的角度来看,他首先寻找这样的逻辑将是 Startup.cs
文件。所有示例和模板都将身份、Entity Framework 初始化等逻辑放在其中。因此,作为惯例,我建议将初始化内容放在那里。
我同意 OP。
我的场景是我想在服务注册表中注册一个微服务,但在微服务 运行.
之前无法知道端点是什么
我觉得 Configure 和 ConfigureServices 方法都不理想,因为它们都不是为执行这种处理而设计的。
另一种情况是想要预热缓存,这也是我们可能想要做的事情。
已接受的答案有多种选择:
创建另一个在您的网站之外执行更新的应用程序,例如部署工具,它在启动网站之前以编程方式应用数据库更新
在您的 Startup class 中,使用静态构造函数确保网站已准备好启动
更新
我认为最好的做法是像这样使用 IApplicationLifetime 接口:
public class Startup
{
public void Configure(IApplicationLifetime lifetime)
{
lifetime.ApplicationStarted.Register(OnApplicationStarted);
}
public void OnApplicationStarted()
{
// Carry out your initialisation.
}
}
这可以通过创建一个 IHostedService
实现并使用 IServiceCollection.AddHostedService<>()
在 ConfigureServices()
中注册它来完成 class。
例子
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
实现。
- 我可以推荐这个博客 post 以获取更多信息,以及如何使用异步的示例:https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/
- 有关更多背景知识,请参阅此讨论:https://github.com/dotnet/aspnetcore/issues/10137
仔细阅读 documentation for ASP.NET Core,有两种启动方法:Configure 和 ConfigureServices。
这些似乎都不是放置我想要在启动时 运行 的自定义代码的好地方。也许我想在我的数据库中添加一个自定义字段(如果它不存在)、检查特定文件、将一些数据植入我的数据库等。我想 运行 一次的代码,就在应用程序启动时。
是否有 preferred/recommended 方法来执行此操作?
在启动时,此类自定义代码基本上有两个入口点。
1.) Main
方法
作为一个 ASP.NET 核心应用程序有很好的旧 Main
方法作为入口点,你可以将代码放在 ASP.NET 核心启动的东西之前,比如
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
class
正如您在问题中所述,Configure
和 ConfigureServices
是放置自定义代码的好地方。
我更喜欢 Startup
class。从运行时的角度来看,调用是在启动时调用还是在 host.Run()
调用之前的其他地方调用并不重要。但是从一个习惯于 ASP.NET 框架的程序员的角度来看,他首先寻找这样的逻辑将是 Startup.cs
文件。所有示例和模板都将身份、Entity Framework 初始化等逻辑放在其中。因此,作为惯例,我建议将初始化内容放在那里。
我同意 OP。
我的场景是我想在服务注册表中注册一个微服务,但在微服务 运行.
之前无法知道端点是什么我觉得 Configure 和 ConfigureServices 方法都不理想,因为它们都不是为执行这种处理而设计的。
另一种情况是想要预热缓存,这也是我们可能想要做的事情。
已接受的答案有多种选择:
创建另一个在您的网站之外执行更新的应用程序,例如部署工具,它在启动网站之前以编程方式应用数据库更新
在您的 Startup class 中,使用静态构造函数确保网站已准备好启动
更新
我认为最好的做法是像这样使用 IApplicationLifetime 接口:
public class Startup
{
public void Configure(IApplicationLifetime lifetime)
{
lifetime.ApplicationStarted.Register(OnApplicationStarted);
}
public void OnApplicationStarted()
{
// Carry out your initialisation.
}
}
这可以通过创建一个 IHostedService
实现并使用 IServiceCollection.AddHostedService<>()
在 ConfigureServices()
中注册它来完成 class。
例子
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
实现。 - 我可以推荐这个博客 post 以获取更多信息,以及如何使用异步的示例:https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/
- 有关更多背景知识,请参阅此讨论:https://github.com/dotnet/aspnetcore/issues/10137