ASP.NET Core中的应用程序启动代码

Kyl*_*ard 31 c# startup asp.net-core

阅读ASP.NET Core文档,有两种方法可以选择Startup:Configure和ConfigureServices.

这些似乎都不是放置我想在启动时运行的自定义代码的好地方.也许我想在我的数据库中添加自定义字段(如果它不存在),检查特定文件,将一些数据播种到我的数据库中等等.我想运行一次的代码,只是在应用程序启动时.

是否有一个首选/推荐的方法来实现这一目标?

Pro*_*ing 18

我同意OP.

我的方案是我想在服务注册表中注册微服务,但在微服务运行之前无法知道端点是什么.

我觉得Configure和ConfigureServices方法都不理想,因为它们都不是为了进行这种处理而设计的.

另一种情况是想要加热缓存,这也是我们可能想做的事情.

接受的答案有几种替代方案:

  • 创建另一个在您的网站之外执行更新的应用程序,例如部署工具,它在启动网站之前以编程方式应用数据库更新

  • 在Startup类中,使用静态构造函数来确保网站已准备好启动

更新

在我看来,最好的办法是使用IApplicationLifetime接口,如下所示:

public class Startup
{
    public void Configure(IApplicationLifetime lifetime)
    {
        lifetime.ApplicationStarted.Register(OnApplicationStarted);
    }

    public void OnApplicationStarted()
    {
        // Carry out your initialisation.
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,IApplicationLifetime 在 .NET 3.x 中已弃用,新接口现在称为:IHostApplicationLifetime (3认同)
  • 我发现请求处理已经开始(它已经开始执行中间件),而OnApplicationStarted方法还没有完成.在我的情况下,它是在数据库尚未更新时启动事务.ApplicationStarted文档也说:"当应用程序主机完全启动并且即将等待正常关闭时触发." 在请求处理开始之前,它并不表示它不是一些初始化内容的地方. (2认同)

Zer*_*ro3 12

这可以通过创建一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHostedService<MyInitializer>();
    }
}
Run Code Online (Sandbox Code Playgroud)

笔记

  • 在我看来,这是最好的方法,当有人只想“一劳永逸”时,你仍然可以这样做,但你仍然能够从 DI 获得服务。请记住, IServiceProvider 您可以获得的是主根,因此如果您想获得一些作用域思考,您需要首先创建作用域 (2认同)

Ral*_*ing 10

基本上,启动时此类自定义代码有两个入口点.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

2.)使用你的Startup课程

正如您在问题中所述Configure,ConfigureServices这是您自定义代码的好地方.

我更喜欢Startup上课.从运行时的角度来看,如果在启动时或在host.Run()调用之前的其他地方调用调用,则无关紧要.但是从程序员的角度来看,谁已经习惯了ASP.NET框架,那么他第一次看到这样的逻辑就是Startup.cs文件.所有样本和模板都为Identity,Entity Framework初始化等提供了逻辑.因此,作为惯例,我建议将初始化内容放在那里.

  • OP 说“这些似乎都不是放置自定义代码的好地方”,并不是说它们是一个好地方。 (5认同)