Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where to put your initialization steps in ASP.NET Core Web Api?

If you familiar with production code you always encounter logic which needs to be invoked before anything should be requested/processed in your service.

I personally wrap it up into something like this and invoke it from DI framework:

public interface IMigrator
{
    Task UpdateAsync();
}

For example:

  • database migration from code
  • static cache initializations
  • seed apply to database
  • authentication of root account,
  • ...

I'm not so proficient with Web API framework at the moment and need to know, where should one put that logic? In Startup.Configure? Is it appropriate? How things turn out if it takes, say 10 minutes?

Need your advise:

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();
    }
}

EDIT:

Found related article which describes how one should do initialization and where. And how to do this asynchronous - https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-part-1/

like image 682
eocron Avatar asked Nov 16 '25 19:11

eocron


1 Answers

Found answer in link above. We can use IHostedService interface starting from .Net Core 3.0 especially for those tasks. Important note is that lower versions IS NOT SUITABLE, because they are not waiting StartAsync methods to complete before serving user requests:

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.
   }
}

Then register it in your DI and Configure method:

    // 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>());
    }

The pros:

  • No woo-doo magic with async wait in sync context. Everything async/cancellable, non-deadlocking.
  • It has gracefull shutdown, in case you hold some unmanaged or other resources in your initialization that needs to be disposed.
  • It has full support of Dependency Injection.

The cons:

  • StopAsync will not be invoked on exceptions. Be cautios, use Dispose too.
  • Watch for version of framework, accidental switch to lower version will cause you world of pain.
like image 51
eocron Avatar answered Nov 18 '25 10:11

eocron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!