Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SignalR with IoC (Castle Windsor) - which lifetime for hubs?

I'm just starting out with SignalR, and have created a custom resolver for SignalR, so I can use Castle Windsor to inject dependencies via hub constructors.

I kind of assumed that I would only need to register the dependencies, but I found that it was also necessary to register the hubs themselves before my app would work. Is this expected? If so, what lifetime should I use for hubs?

like image 888
Andrew Stephens Avatar asked Jan 14 '14 10:01

Andrew Stephens


1 Answers

By default SignalR does not register each hub with the dependency resolver. Instead it uses an IAssemblyLocator to find available assemblies that might contain SignalR Hubs. Then the IHubDescriptorProvider searches through all the available assemblies for Hubs and creates HubDescriptors.

Lastly, the IHubActivator takes a HubDescriptor and returns a newly instantiated SignalR hub (using Activator.CreateInstance) unless the Hub type associated with the HubDescriptor has been registered with the dependency resolver. In the latter case, the Hub returned from the IHubActivator will be taken directly from the dependency resolver.

Typically SignalR hubs are ephemeral meaning that they get created and destroyed for each Hub method invocation. This means that if you register your Hub with SignalR's dependency resolver, you should make sure that a new Hub instance is returned each time SignalR resolves the Hub type.

I strongly advise against registering a singleton Hub for several reasons:

  1. Hub methods can be called in parallel. When this happens, Hub.Context can be overridden as part of the setup for another method call. This can lead to really subtle bugs. For example, with a singleton Hub, the following code might add a connection other than the caller to a group (which could obviously be a big security issue):

    [Authorize(Roles="Admin")]
    public async Task JoinAdminGroup()
    {
        await Groups.Add(Context.ConnectionId, "admin");
    }
    
  2. Hub.Dispose will be called after each activation. If you keep returning the same Hub, it's Dispose method will be repeatedly called. This probably won't affect you unless you implement Dispose on your Hubs, since the default Dispose implementation currently no-ops.

  3. IIS recycles AppDomains. When this happens, you will be forced to reinstantiate your Hub anyway. Remember, SignalR will automatically reestablish active connections after your app becomes unavailable for a short period of time (as is the case with an AppDomain recycle), so you can very well have a newly instantiated Hub dealing with pre-existing connections even if you register your Hub as a Singleton with the dependency resolver.

https://github.com/SignalR/SignalR/blob/2.0.1/src/Microsoft.AspNet.SignalR.Core/DefaultDependencyResolver.cs#L79

like image 166
halter73 Avatar answered Sep 28 '22 11:09

halter73