简体   繁体   中英

Run async code during startup in a ASP.Net Core application

After changing the signature of the function ConfigureServices to be asynchronous (originally it was just a void synchronous function and the application worked perfectly fine), I get the following error:

Unable to find the required services. Please add all the required services by calling IServiceCollection.AddAuthorization inside the call to ConfigureServices(...) in the application startup code.

Below is the code of my ConfigureServices function.

// This method gets called by the runtime. Use this method to add services to the container.
public async Task ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages();

    // Create the necessary Cosmos DB infrastructure
    await CreateDatabaseAsync();
    await CreateContainerAsync();
}

ConfigureServices is automatically called at runtime.

You can't just change the signature, it needs to be void to be called by the framework.

Right now when you changed it to Task it means that the framework can't find it so it will not be called at all.

There's a GitHub issue regarding this here: https://github.com/dotnet/aspnetcore/issues/5897

It's quite tricky though...

There's no progress for 5.0 no, we don't know how to do this without blocking or breaking changes. It might be possible to run filters in 2 stages that never overlap.

Update based on your comment: If you want to run something async during startup, I usually do like this:

I create a interface like this:

public interface IStartupTask
{
     Task Execute();
}

Then a sample implementation like this

public class CreateDatabaseStartupTask : IStartupTask
{
    public async Task Execute()
    {
          // My logic here
          // await CreateDatabaseAsync();
    }
}

Then in my Program.cs

public static async Task Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();
    
    // Resolve the StartupTasks from the ServiceProvider
    var startupTasks = host.Services.GetServices<IStartupTask>();
    
    // Run the StartupTasks
    foreach(var startupTask in startupTasks)
    {
        await startupTask.Execute();
    }
    await host.RunAsync();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });
}

And my Startup

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<IStartupTask, CreateDatabaseStartupTask>();
    }
}

So the important things are:

  1. Register your StartupTasks
  2. Build the host
  3. Resolve the StartupTasks
  4. Run the StartupTasks
  5. Start the Host

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM