IHubContext<THub> "Singleton access" (Dependency Injection) #2347
Comments
IHubContext is a singleton and already works as you would expect without writing custom code. Just inject it into your class and you can call methods. |
Hi David, I figured out was the problem was: I used a different IoC Container. In the Injecting the |
@davidfowl I'm actually using this method but the instance that is injected appears to have no connections. I've verified that my hub is communicating with my frontend perfectly fine from the hub directly, but when I try to send a message to the same methods from a class that injects IHubContext, the messages do not go out. When I debug and dig through the private fields, the list of connections has a count of 0. I've tried sending messages directly to |
Put a repro of the bug somewhere. It’s likely you’re creating another DI container or something strange like that. To prove it, make a new project and try to create a minimal repro of the bug. |
I'm certainly creating another DI container (Autofac)... I'm using NServiceBus and they don't yet have an IServiceCollection adapter , so I'm populating the Autofac container from the IServicesCollection. I'll comb through that again and see if it's not transferring over some registrations groan |
I wasn't able to find the registration in the Autofac builder... interesting. I removed that from the pipeline and tried a direct registration with NServiceBus and still no luck. I tested the DI with a controller to rule out a problem with the SignalR installer, but it worked fine. I'll take this up with Particular. Thanks. |
Sounds like you probably have 2 container universes. That won’t work. You need to capture the instance from the web application. |
Actually you know what, I tried a more direct approach and it's not working. So if I request the service in something like the Hub ctor, it comes in fine. I can see it has 1 connection. But if I request the service from IServiceCollection.GetRequiredService<> then I get an instance with no connections:
I verified that every time my handler spins up by placing a break point in ... maybe |
Repro: https://github.com/dasjestyr/SignalRTest1 NSB Installer is where IServiceCollection is called per request; located at If you run the demo, you can see that the messages go out when the Hub is contacted directly, but the DI'd service There is also a demo of how it was done in an older version that didn't have this problem since it was getting the context from what looked like a service locator: https://docs.particular.net/samples/near-realtime-clients/ |
I think I figured it out. I needed to completely replace
and then return the new provider from the NSB installer. I forgot you could even do that... e.g. public IServiceProvider ConfigureServices(IServiceCollection services)
{
// other registrations happen here...
// this is the last one since it's what creates the autofac provider
// from IServiceCollection
return services.AddNsb();
} Clearly there's some voodoo going on in that implementation that keeps those things in sync. Seems that everything is working now. Looking forward to Particular creating an official adapter for their DI... |
We periodically close 'discussion' issues that have not been updated in a long period of time. We apologize if this causes any inconvenience. We ask that if you are still encountering an issue, please log a new issue with updated information and we will investigate. |
Hi there,
im currently working with ASP.NET Core SignalR 1.0.0-rc1-final (.Net Core 2.1.300-rc1).
In my application I want to be able to access my hub/clients anytime from the backend (singleton).
As far as I have studied the source code, access to e.g. the
IHubContext<THub>
is only possible in a scoped manner. Or did I miss something?I already tried to register my own service as a singleton and inject the IHubContext. However, there were no connections in there. I think, because I was out of scope he created a new object. When I inject in e.g. my HomeController's constructor I get the correct, scoped, IHubContext with the expected number of connections. (https://github.com/aspnet/SignalR/issues/1699)
In SignalR for ASP.NET I can get access to the
IHubContext
e.g. viaGlobalHost.ConnectionManager.GetHubContext<THub>();
(see https://docs.microsoft.com/en-us/aspnet/signalr/overview/getting-started/tutorial-high-frequency-realtime-with-signalr#add-the-server-loop )My current, and dirty approach, is to make a new class which inherits from the
DefaultHubDispatcher
. This class stores a static variable of the injected IHubContext. Then I add my customHubDispatcher
as a singleton to the .Net DI.Another idea I had was to write my own
HubLifetimeManager
(however, calling thepublic virtual ValueTask WriteAsync(SerializedHubMessage message, CancellationToken cancellationToken = default)
method in application code is not intended.Furthermore, I thought of adding/removing my typed clients in an static accessible concurrent dictionary in my custom hub implementation in the
OnConnectAsync
andOnDisconnectAsync
methods of theHub
.The text was updated successfully, but these errors were encountered: