36

I have an aspnetcore app.

During startup, it does the usual startup actions.

After these are complete, I need to do some verification to ensure it was set up correctly. In particular, I need to call a stored procedure in the database using the default connection string. In other words, I need to create a class that uses dependency injection so that needs to be complete before it is called.

Just not sure where to put such code in StartUp.

Greg Gum
  • 33,478
  • 39
  • 162
  • 233
  • Show what you have so far and lets see if we can help you along. Right now with no [mcve] the question is a bit broad. – Nkosi Jun 08 '18 at 15:19
  • Ok, good point. Will do so. – Greg Gum Jun 08 '18 at 15:20
  • When updating your question, please also confirm whether or not you need `Configure` to run before your verification code. – Kirk Larkin Jun 08 '18 at 16:33
  • 2
    this may be useful for you: [ASP.NET Core app's start/stop/error events](https://stackoverflow.com/questions/41675577/where-can-i-log-an-asp-net-core-apps-start-stop-error-events/41676005#41676005) – Set Jun 10 '18 at 09:11

3 Answers3

33

Probably the best place is in Configure method after UseMvc() call. That is also the place where you usually apply migrations. You can add as many classes that DI knows as parameter.
For example:

public void Configure(IApplicationBuilder app)

or

public void Configure(IApplicationBuilder app, AppUserManager userManager, IServiceProvider serviceProvider)

or

public void Configure(IApplicationBuilder app, MyDbContext context)

If you want to check this in background (only if you don't care about result - application should run also if verification fails), check my answer here.
Also this answer may help you.

Makla
  • 9,899
  • 16
  • 72
  • 142
11

Since .net core 2.0, you should probably implement your own IHostedService. Each registered IHostedService will be started in the order they were registered. If they fail, they can cause the host to fail to start.

Since you wish to perform database operations, you should also create a new service scope to control the lifetime of your database connection.

public class StartupService : IHostedService{
    private IServiceProvider services;
    public StartupService(IServiceProvider services){
        this.services = services;
    }
    
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        using var scope = serviceProvider.CreateScope();
        using var context = scope.ServiceProvider.GetRequiredService<...>();
        ... do work here
    }
}

// then in configure services
services.AddHostedService<StartupService>();

Note that EF Core 5 introduces IDbContextFactory, which could be used to create a context outside of any DI service scope.

Each of the other answers to this question will run while the web server is being configured, which is also executed within an IHostedService.

Jeremy Lakeman
  • 9,515
  • 25
  • 29
  • Are you suggesting to get a service using `IDbContextFactory` as the last statement of the `Configure` method? Core 5 is fairly new and I don't want to make the mistake of getting stuff to work while actually screwing them up, which isn't realized until a critical later stage. – Konrad Viltersten Jan 29 '21 at 07:22
  • I would only use that if you aren't using DI. From memory your `Startup.Configure` method is called by another `IHostedService`, you could put a breakpoint inside it and check the call stack to confirm that. – Jeremy Lakeman Jan 30 '21 at 09:07
  • Got ya. I'm using DI (as one should in .NET Core, hehe), so that's not an option. What I'm a bit unclear about is what precisely invokes the method `StartAsync`. Does it happen automagically when we register the service? I've thought that the order of **registering** services didn't matter (only that **adding** them did). However, per your answer, how can we then know that an earlier service is active as we get to the starting method of ours? (I'll be doing seeding so I want the DB context to be ready to go.) – Konrad Viltersten Jan 30 '21 at 22:03
  • Your main method is likely calling `IHost.RunAsync()` which would call `StartAsync` then block until shutdown. You can find the implementation here; https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs#L51. The default implementation of `services.GetService>` returns all services that implement `T`, in the order they were registered. – Jeremy Lakeman Jan 31 '21 at 23:45
7

Or use IStartupFilter.

This is mainly for configuring middleware, but should allow you to perform actions after the configuration is over.

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/startup?view=aspnetcore-2.1#extend-startup-with-startup-filters

frostymarvelous
  • 2,786
  • 32
  • 43