1

I am converting my startup code into new ServiceStack Modular Startup approach and have hit a snag.

I have this code in old startup

public void Configure(IApplicationBuilder app)
{
    app.UseHangfireDashboard(hangfirePath, new DashboardOptions
    {
        Authorization = new[] { new HangFireAuthorizationFilter() }
    });

    var appHost = new AppHost
    {
        AppSettings = settings
    };

    app.UseServiceStack(appHost);

    var container = appHost.Resolve<Container>();

    GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));

    app.UseHangfireServer();
}

It's important that app.UseHangfireDashboard is registered before app.UseServiceStack or the dashboard wont work.

I got it working all fine except for the part where it links the IoC container to hangfire:

GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));

This is the working code without linking container:

[Priority(-1)]
public class ConfigureHangfirePostgreSql : IConfigureServices, IConfigureApp
{
    IConfiguration Configuration { get; }
    public ConfigureHangfirePostgreSql(IConfiguration configuration) => Configuration = configuration;
    public void Configure(IServiceCollection services)
    {
        var conn = Configuration.GetValue<string>("database:connectionString");
        services.AddHangfire((isp, config) =>
        {
            config.UsePostgreSqlStorage(conn, new PostgreSqlStorageOptions
            {
                InvisibilityTimeout = TimeSpan.FromDays(1)
            });

            config.UseConsole();

        });
    }

    public void Configure(IApplicationBuilder app)
    {

        app.UseHangfireDashboard("/hangfire", new DashboardOptions
        {
            Authorization = new[] { new HangFireAuthorizationFilter() }
        });

        // commented out because I dont think it's possible to get container yet and also code doesn't work
        //var container = app.Resolve<Container>();
        //GlobalConfiguration.Configuration.UseActivator(new ContainerJobActivator(container));         

        app.UseHangfireServer();

    }
}

I am setting the priority to -1 so it runs before servicestack is registered. Because of that I guess the container isn't yet created so I need to make another module to run after like this:

[Priority(2)]
public class ConfigureHangfirePostgreSqlPost : IConfigureApp
{
    public void Configure(IApplicationBuilder app)
    {
        //how do I resolve container here?
    }
}

The container isn't registered as a service (as I am asking the container for the service) so im not sure how I am able to access it.

What is the right way of getting hold of the container in a startup module?

mythz
  • 141,670
  • 29
  • 246
  • 390
Guerrilla
  • 13,375
  • 31
  • 109
  • 210

1 Answers1

0

It's hard to decipher what the actual question is, answering a clear one found on the last line:

What is the right way of getting hold of the container in a startup module?

This existing answer has a good summary of ASP.NET Core IOC, where you can access any singleton dependencies from app.ApplicationServices, e.g:

public void Configure(IApplicationBuilder app)
{
    var serviceProvider = app.ApplicationServices;
    var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Is it possible to get the `Funq.Container` object? In old code that is passed to a method that joins the 2 IoC so dependency injection works with Hanghfire – Guerrilla Dec 29 '19 at 03:21
  • @Guerrilla No for the reasons you've already deduced from your answer, ServiceStack's AppHost hasn't been created yet. Any dependencies you need before AppHost configuration should be registered in ASP.NET Core's IOC, [all of which are later accessible from ServiceStack's Funq.Container](https://docs.servicestack.net/netcore#net-core-container-adapter). – mythz Dec 29 '19 at 03:24
  • But I am changing priority on second class so it should have been created at that point right? – Guerrilla Dec 29 '19 at 03:28
  • @Guerrilla No its literally only created in your code at `new AppHost`, it does not exist prior. Modular Startup is independent from your AppHost, its purpose is to auto-configure "no touch" Startup / Configuration classes. I don't see why you can't register it in ASP.NET's IOC and resolve the same dep later in Func IOC? You could also initialize a static property and resolve it in Startup logic that's executed afterwards. – mythz Dec 29 '19 at 03:33
  • @Guerrilla to clarify your AppHost instance is only created at `new AppHost`, an instance is created to execute any [Configure(IServiceCollection services)](https://docs.servicestack.net/modular-startup#register-aspnet-core-dependencies-in-apphost), but its not your AppHost instance, if you wanted to share dependencies between instances you can register it in ASP.NET Core's IOC or populate a static property. – mythz Dec 29 '19 at 03:37
  • 1
    Ah OK, I didn't realise that I probably need to spend some time looking at how that part works. I will give it a go, thanks for help – Guerrilla Dec 29 '19 at 03:55