SignalR + Autofac + OWIN: Why doesn't GlobalHost.ConnectionManager.GetHubContext work?

mutex picture mutex · Jan 15, 2014 · Viewed 8.3k times · Source

I'm trying to use OWIN, SignalR and Autofac in a single project.

I'm setting things up with regards to signalR as follows:

       // Create the AutoFac container builder:
        var builder = new ContainerBuilder();

        // ...[Register various other things in here]...

        // register signalR Hubs
        builder.RegisterHubs(Assembly.GetExecutingAssembly());

        // Build the container:
        var container = builder.Build();

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            Resolver =  new AutofacDependencyResolver(container)
        });

My issue is that when I use the Autofac SignalR integration, I can no longer get a signalR Hub Context on the server (in a webapi controller for example) and so can't send messages from server side to the connected clients. Something like the following is how I do this when I'm not using the Autofac signalR integration:

var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();
hubContext.Clients.All.notification("Test Message");

But this doesn't work when I add Autofac into the mix - I don't get any error message and I do seem to get a hubContext, but calls on it don't actually seem to get to the clients.

If I comment out the use of the dependency resolver for signalR in the call to MapSignalR, the call to GetHubContext works again and messages reach the signalR clients sucessfully, but of course I can no longer use IoC on my hubs. e.g.

        // Configure SignalR with the dependency resolver.
        app.MapSignalR(new HubConfiguration
        {
            // Resolver =  new AutofacDependencyResolver(container)
        });

Can anybody tell me why using the AutofacDependencyResolver stops GlobalHost.ConnectionManager.GetHubContext from working correctly??

NOTE: One other thing I have tried is instead of using GlobalHost.ConnectionManager.GetHubContext() I tried injecting an IConnectionManager into the webapi controller from which I want to send a message to clients, then calling GetHubContext on that, but Autofac couldn't resolve the IConnectionManager.

I did find the following article by Piotr Szmyd which apparently allows this:

http://www.szmyd.com.pl/blog/wiring-signalr-with-autofac

but this appears to be based on obsolete signalR builds, and while there seems to be a nuget package for it here:

http://www.nuget.org/packages/SignalR.AutoFac/

it also seems well out of date.

Answer

halter73 picture halter73 · Jan 15, 2014

If you use a custom dependency resolver with SignalR, you can no longer use GlobalHost unless you modify it:

GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();

// A custom HubConfiguration is now unnecessary, since MapSignalR will
// use the resolver from GlobalHost by default.
app.MapSignalR();

If you don't want to modify GlobalHost, you will have to manually resolve your IConnectionManager:

IDependencyResolver resolver = new AutofacDependencyResolver(container);
IHubContext hubContext = resolver.Resolve<IConnectionManager>().GetHubContext<MyHub>();

app.MapSignalR(new HubConfiguration
{
    Resolver = resolver
});