4

I'm trying to implement a new extension method for the IWebHostBuilder that executes some code, like registering somewhere. The important part is, that it also unregisters when the application is shutting down.

I added some code which shows what I want to do. The problem here is, that the instance of IApplicationLifetime is not available yet. This new extension method was added last in the pipeline of building the WebHost.

public static IWebHostBuilder UseHttpGatewayappRegistration(this IWebHostBuilder webHostBuilder)
    {
        webHostBuilder.ConfigureServices(services =>
        {
            var sp = services.BuildServiceProvider();

            // This instance is not available
            IApplicationLifetime applicationLifetime = sp.GetService<IApplicationLifetime>();

            // These instances are ok
            AppSettings appSettings = sp.GetService<AppSettings>();
            ILoggerFactory loggerFactory = sp.GetService<ILoggerFactory>();

            var registration = new Registration(loggerFactory.CreateLogger<Registration>());

            applicationLifetime.ApplicationStopping.Register(() =>
            {
                registration.Unregister();
            });
        });

        return webHostBuilder;
    }

Why is the IApplicationLifetime instance null, even though I added this extension method last in the pipeline of building the WebHost pipeline? It would be great, if someone would provide me with some information about the execution order of all "ConfigureServices" methods and how or if it is at all possible to use IApplicationLifetime in a ConfigureServices method.

I know I could do this all without the WebHostBuilder, but it seems logical to me to do it there and I also think there has to be a way.

Unfortunately I couldn't find much information online...

Thank you.

EDIT: I found a way to use DI in ConfigureServices methods. I edited the question accordingly. This helped me: How to Resolve Instance Inside ConfigureServices in ASP.NET Core

Community
  • 1
  • 1
timothy3001
  • 765
  • 2
  • 8
  • 17

1 Answers1

5

You can't get access to IApplicationLifetime instance from ConfigureServices method. It's by design. Check the "Services Available in Startup" section here: Application Startup in ASP.NET Core.

Resolve IApplicationLifetime in the IWebHostBuilder.Configure method (it replaces the Startup.Configure method if it is used later in IWebHostBuilder configuration pipeline):

public static IWebHostBuilder Foo(this IWebHostBuilder webHostBuilder)
{
    webHostBuilder.Configure(x =>
    {
        var service = x.ApplicationServices.GetService<IApplicationLifetime>();
    });

    return webHostBuilder;
}

It's also possible to extend the original Startup.Configure method instead of replace (a lot of Reflection logic should be added to make this solution reliable):

.Configure(app =>
{
    var env = app.ApplicationServices.GetService<IHostingEnvironment>();
    dynamic startup = Activator.CreateInstance(typeof(TStartup), env);

    //Carefully resolve all input parameters.
    //Make sure all required services are registered in DI.
    startup.Configure(app, env);

    var lifetime = app.ApplicationServices.GetService<IApplicationLifetime>();
})
Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
  • Mhmm ok thank you... I already tried to use the `Configure` method. The problem is, I also use a `Startup` class in parallel, so when I call the `Configure` method in my extension method, the `Configure` method in the `Startup` class isn't called anymore... – timothy3001 Apr 27 '17 at 09:03
  • @timothy3001, I guess it's impossible to register a service in `Configure` method. So, even if we create a `Startup` instance manually and call `Startup.ConfigureServices` from `Configure` it won't be succeded. Probably it's better to re-design your extention method to a `IApplicationBuilder` extention like this: http://stackoverflow.com/a/43610530/5112433 – Ilya Chumakov Apr 27 '17 at 09:25
  • Ok thank you. I don't really need to register a service in `Configure` method but rather use the `IApplicationLifetime` in a `ConfigureServices` method to have a shutdown hook. My problem with putting it into the `Startup` is, that it doesn't belong there in my opinion. It has nothing to do with the setup of HTTP pipeline. But since there's no alternative for now, I'll go ahead and do that. Thank you – timothy3001 Apr 27 '17 at 09:35
  • @timothy3001, I've added example of original `Startup.Configure` method extending indead of replacement. Maybe it will be helpful. Thanks for the interesting question. – Ilya Chumakov Apr 27 '17 at 10:16
  • Oh wow, thanks a lot :) This seems to me the "cleanest" solution. – timothy3001 May 03 '17 at 07:26