将 ASP.NET Core Web Api 中的初始化步骤放在哪里?

eoc*_*ron 3 c# iis-express docker asp.net-core-webapi entity-framework-migrations

如果您熟悉生产代码,您总是会遇到需要在服务中请求/处理任何内容之前调用的逻辑。

我个人将它包装成这样的东西并从DI框架调用它:

public interface IMigrator
{
    Task UpdateAsync();
}
Run Code Online (Sandbox Code Playgroud)

例如:

  • 从代码迁移数据库
  • 静态缓存初始化
  • 种子应用于数据库
  • root帐户的身份验证,
  • ...

我目前对 Web API 框架不太精通,需要知道应该将该逻辑放在哪里?在Startup.Configure?合适吗?如果需要(比如说 10 分钟),结果会怎样?

需要您的建议:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services
            .AddControllers();
            services.Register(new CoreModule(), new DataModule());
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "api",
                pattern: "api/v1/{controller}/{action}/{id?}");
        });

        //<- somewhere here? does it break some startup logic in IIS like winservices does when process takes longer than 1 minute?
        await _migrator.UpdateAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:

找到了相关文章,其中描述了应该如何进行初始化以及在哪里进行初始化。以及如何执行此异步操作 - https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-part-1/

eoc*_*ron 5

在上面的链接中找到了答案。从.Net Core 3.0开始,我们可以使用 IHostedService 接口,特别是对于这些任务。重要提示是,较低版本不适合,因为它们在服务用户请求之前不会等待 StartAsync 方法完成:

internal sealed class Boot : IHostedService
{
   public Task StartAsync(CancellationToken token){
       //migrate db or whatever here
   }

   public Task StopAsync(CancellationToken token){
       //gracefull shutdown for 5 sec, after which token will blowup. It will still wait for method return.
   }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的 DI 和配置方法中注册它:

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddSingleton<IBoot, Boot>();
        services.AddHostedService(x=> x.GetService<IBoot>());
    }
Run Code Online (Sandbox Code Playgroud)

优点:

  • 同步上下文中的异步等待没有任何魔法。一切都是异步/可取消的,非死锁。
  • 如果您在初始化中持有一些需要处置的非托管资源或其他资源,它可以正常关闭。
  • 它完全支持依赖注入。

缺点:

  • 发生异常时不会调用 StopAsync。请小心,也请使用 Dispose。
  • 注意框架版本,一不小心切换到低版本会给你带来痛苦。