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?
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 HubDescriptor
s.
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:
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");
}
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With