Asp.net Core MVC - obtaining dependency during app shutdown
Asked Answered
S

1

6

I'm developing a web app using ASP.net Core MVC 2.2, and in my Startup class I'm registering a dependency injection of type MyService, like so:

public void ConfigureServices(IServiceCollection services)
{
    //Inject dependency
    services.AddSingleton<MyService>();

    //...other stuff...
}

This works correctly. However, I need to retrieve the instance of MyService during application shutdown, in order to do some cleanup operations before the app terminates.

So I tried doing this - first I injected IServiceProvider in my startup class, so it is available:

public Startup(IConfiguration configuration, IServiceProvider serviceProvider)
{
    ServiceProvider = serviceProvider;
    Configuration = configuration;
}

and then, in the Configure method, I configured a hook to the ApplicationStopping event, to intercept shutdown and call the OnShutdown method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
{
    //Register app termination event hook
    applicationLifetime.ApplicationStopping.Register(OnShutdown);

    //...do stuff...
}

finally, in my OnShutdown method I try obtaining my dependency and using it:

private void OnShutdown()
{
    var myService = ServiceProvider.GetService<MyService>();
    myService.DoSomething(); //NullReference exception, myService is null!
}

However, as you can see from the comment in the code, this doesn't work: the returned dependency is always null. What am I doing wrong here?

Smasher answered 12/9, 2019 at 7:41 Comment(0)
B
13

I was able to make it work by explicitly passing your application services to your shutdown method like so.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime)
{
    //Register app termination event hook
    applicationLifetime.ApplicationStopping.Register(() => OnShutdown(app.ApplicationServices));

     //...do stuff...
}


private void OnShutdown(IServiceProvider serviceProvider)
{
        var myService = serviceProvider.GetService<MyService>();
         myService.DoSomething();
}

Bare in mind that this will work for singleton services - you may have to CreateScope() if you want to resolve scoped services.

Bethanybethe answered 12/9, 2019 at 8:40 Comment(4)
This worked perfectly. I don't know if the provider is actually disposed (shouldn't it throw some exception if that's the case?) but capturing it in the lambda like you did solved the problem! Thanks.Smasher
@Smasher My next guess would be you are injecting your ServiceProvider in the startup class constructor , at time of injection your Service Provider has not been built yet.Bethanybethe
@Bethanybethe How did you know to use a lambda expression? I was trying .Register(OnShutdown(app.ApplicationServices) and getting errors.Quickwitted
@PaulMcCarthy to be entirely honest - Resharper suggested it.Bethanybethe

© 2022 - 2024 — McMap. All rights reserved.