Support for Microsoft.Extensions.DependencyInjection?

Ah @jstafford I get what you are saying. I looked at the problem from the wrong angle. The downsides of the uniform container that we introduced is that as you rightfully stated we require the container implementation to enable injection into handlers. Since we are currently (maybe not yet :wink: ) providing a container implementation for the Microsoft.Extensions.DependencyInjection you need another container such as Autofac to bridge between.

I see… Ok I’ll just use the Autofac bridge for now then. Hopefully we’ll see NServiceBus.MicrosoftDI (or whatever) before too long :slight_smile:

@jstafford I have created an internal issue to get this done. At this point, I don’t have an ETA for it but can let you know once it gets prioritized.

That’s all I can ask for! Thanks!

Welp… it finally bit me. I’m playing with netcore2.1 release of SignalR and it would seem that the Autofac solution for copying registrations is not fully working. I can see that the IHubContext<T, K> registrations are in IServiceCollection but they’re not being copied over to the Autofac builder. No errors. No clue what’s up. Point is… a first class, supported IServiceCollection implementation would be swell.

1 Like

Please have a look at NServiceBus.MSDependencyInjection.

3 Likes

Hi Toni

Great stuff!. Would you want to add this to our docs site?

If you need help to get it going feel free to ping me at daniel dot marbach at particular dot net

Regards
Daniel

Awesome! I just gave it a try in a test project and things seem to be in working order. Straight into production, what could go wrong amirite? :smiley:

We already use it in production :wink:.

1 Like

Bangarang. I’m all over this, thank you!

For the reference, we recently added the extension to our docs site

Regards
Daniel

@twenzel ach… ok so this still has the same problem I was having with Autofac in that the services aren’t being updated. For example, services.AddSignalR registers IHubContext<T> which is needed if an NSB handler ever hopes to being to communicate with a user connected to the hub. The problem is that as user connect and disconnect from the hub, IHubContext gets updated by the framework. It would appear that those changes aren’t being picked up in NSB’s internal service collection, almost as if the service collection is being copied from IServiceCollection instead of adapted, if that makes sense. I haven’t actually looked at the code yet, but this is what I guess is happening.

The result is:

  • service starts up
  • The current state of IHubContext is registered with NSB
  • A user connects and IHubContext is updated with that connection info
  • A message is received by the NSB handler which requests IHubContext
  • The handler tries to send a message to the connected user but the user’s connection doesn’t exist on this instance of IHubContext
  • The user never receives the message

I believe this is fixable in some way as I was able to find a workaround with the Autofac container by actually replacing the default netcore service provider with Autofac.Extensions.DependencyInjection.ActofacServiceProvider.

I don’t know for sure, but I think what might be happening is that the Autofac extension might be wrapping service definitions in adapters instead of creating new service definitions for NSB so that any changes are made available. So if I’m correct about the implementation, then I think the fix would be to not copy service definitions but create adapters instead.

A bit more info in the issue I opened up a while ago including a repro and the autofac workaround described: IHubContext<THub> "Singleton access" (Dependency Injection) · Issue #2347 · aspnet/SignalR · GitHub

I was able to verify that this is not a problem with SignalR but rather a problem with how libraries are interfacing with NSB’s IoC container. Autofac is an ok workaround at the moment, but I’d REALLY rather not being dealing with THREE different IoC containers, you know?

Hi @twenzel, @jstafford, @simoncropp,

Your input would be appreciated

Thanks Daniel

Any headway on this? We are also stuck with the SignalR issue and how NSB is copying (instead of adapting) services from the IServiceProvider. Our workaround right now is to place all needed HubContext instances in global static variables instead of using IoC in the NSB handlers. Very bad practice, but don’t have another solution. We do not want to introduce AutoFac as a bridge.

I’d really love to see first-class support for this. The new Azure AppService WebJobs 3.0 uses MsExtDI out-of-the-box as well as HostBuilder

2 Likes

Hi, I have the same problems while testing with SignalR in a Handler. In an Controller it works fine and the IHubContext has connections.
In a handler the IHubContext has no connections and we can’t send something to the Clients.

It is the same behavior like described from @jstafford and @NArnott.

I also don’t want to use Autofac and the workaround to store it in a static variable sounds not very good.

kind regards

I’ve finally found some time to investigate the issue with SignalR and the Microsoft Dependency Injection integration for NServiceBus. The root cause of the issue is how the integration works, it ends up creating a separate container instance that is not shared with ASP.Net Core runtime, causing components resolution to misbehave.

I have a very raw fix for it, I raised a draft PR to discuss with maintainers how to proceed.

Thanks to @twenzel NServiceBus.MSDependencyInjection 0.1.4 is now available on nuget: NuGet Gallery | NServiceBus.MSDependencyInjection 0.1.4

The PR I raised had been merged and it’s now possible to configure an ASP.Net Core project like in the following snippet:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddSignalR();
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    IEndpointInstance endpointInstance = null;
    services.AddSingleton<IMessageSession>(_ => endpointInstance);

    var ec = new EndpointConfiguration("some-endpoint-name");
    ec.UseTransport<ATransport>();

    UpdateableServiceProvider container = null;
    ec.UseContainer<ServicesBuilder>(c =>
    {
        c.ExistingServices(services);
        c.ServiceProviderFactory(sc => 
        {
            container = new UpdateableServiceProvider(sc);
            return container;
        });
    });

    endpointInstance = Endpoint.Start(ec).GetAwaiter().GetResult();

    return container;
}

Using the above approach the result is that the ASP.Net Core application and the NServiceBus endpoint will effectively share the same container, making sure both can resolve and share the same components.

Please see NServiceBus 7.2.0 - Minor release available

NServiceBus.Extentions.Hosting 1.0.0 is released. Please see announcement post.