Getting Hub Context for ASPNet.Core Signal-R (.NET Core 2.1) RC
I'm using ASP.NET Core 2.1 RC1.
I'm also using Signal-R for it (found here):
https://docs.microsoft.com/en-us/aspnet/core/signalr/javascript-client?view=aspnetcore-2.1
I'm creating a .NET Core console application that's hosting Kestrel and using Signal-R. I've pretty much set it up exactly as the getting started documentation states for setting up the Startup.
This all works great. I'm able to connect to the it, get my HTML with signal-R script in it, receive messages I crafted with Clients.All.SendAsync. Works great.
BUT
I want to be able to send a message to clients, from outside the Hub. Where some event happens in my application, and a message is sent to clients. In full .NET, I'd use the GlobalHost and get the context. In ALL my searches on Stack Overflow, they reference something that no longer works, or used within an REST API controller that's passed in the IHubContext.
I have an event listener in my program.cs, and when the event is triggered, I'd love to be able to send a message to my UserInterfaceHub.
So -- how do I get the hub context in Program.CS - so I can send messages to it (call the SwitchUI method) from within an event delegate I have in Program.CS?
StartUp.cs
Program.CS
UserInterfaceHub.cs
edit adding clarity.
In Program.CS, I have this event delegate:
//now that we're ready, start listening.
await
which is this:
This line of code:
will register your hub with the DI container. Then to get access to it, you either use constructor injection to inject in the IHubContext<UserInterfaceHub>
(this works for example in a Web Controller) or access it directly from the DI container by doing the following:
(for example if executed in the startup.cs Configure
method)
If you don't have access to the app.ApplicationServices
which is basically an IServiceProvider
at the location you need to access the hub, then you will need to either 1) get that class to work with dependency injection to inject in the IHubContext<UserInterfaceHub>
or IServiceProvider
2) Setup a static Services global var via Configure
so that you can have access to one of them globally, or find some other way to access the DI container (aka IServiceProvider) to get your hub via the above line of code.
Once you have your hub, then sending the message to the registered clients is a simple as calling the method on your hub.
You're question is a little unclear, but I'm assuming you mean you want to replace the following with something that can send a message through your hub:
Since this is in your Configure
method, you can simply add IServiceCollection services
to your Configure
methods params. Then, you can do:
However, I'm not sure that this will actually do anything useful ultimately. At startup, you'd logically have no clients with subscriptions yet. As a result, sending a message through your hub at this point, would essentially go nowhere. By the time a user actually hits your site and gets connected to your hub, this part of your application has already run, and won't be hit again.
I encountered a similar situation and here's how to resolve it:
In your Service layer, create an interface called something like ISendHubMessage. Have a method called Send() that takes parameters that you're wanting to send via SignalR. Create a class within the same file called SendHubMessage that implements the interface. Have it just do a return.
In your top-level project (where your Startup.cs file is located) create another class called SendHubMessage that implements that same ISendHubMessage interface from your Service layer. Within this SendHubMessage, you can use DI to get at the hub as explained above. This method will do the actual logic of sending via SignalR.
In your Startup ConfigureServices() method, add the following line:
services.AddTransient<"Service".ISendHubMessage, "TopLevel".SendHubMessage>();
(where "Service" is the namespace to your Service-level project and "TopLevel" in the namespace to your top-level project).
What you're doing with this line is saying "Whenever an object requests the ISendHubMessage dependency from the Service layer, supply it with the SendHubMessage class defined in my top-level project".
Finally, in all the places in code outside of your top-level project that you're wanting to send messages through your hub, inject that ISendHubMessage dependency in the constructor. You can then refer to it in the class methods and when you call Send(), it will call the Send() method defined in your SendHubMessage class in your top-level project.
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.