Search code examples
c#asp.net-mvcsignalrsignalr-hub

Sending SignalR Broadcasts that is running within ASP.NET MVC Application from a Windows Service on the same server


I have an ASP.NET website that uses SignalR hubs to send messages to the website users.

I have the code that calls the hubs within my business layer and I use dependency injection to inject the instances of the hubs up from my ASP.NET application to my business layer.

The problem that I have come up against is when I've come to use my business layer within a Windows Service, that I don't know how to get an instance of the hubs.

Is it possible to 'hook' into my existing SignalR hubs from the server, that are running within my ASP.NET application and send broadcasts from my Windows Service?

I realise that I can connect as a client within my windows service using the following code, but this is the wrong way around, I want to send broadcasts from the server...

// This code enables a client connection
var connection = new HubConnection("http://localhost:3537/");
IHubProxy myHub = connection.CreateHubProxy("NotificationHub");

connection.Start().Wait(); 

myHub.Invoke("setNotificationCount", "5");

Solution

  • Your hubs are hosted in ASP.NET application. So no, there is no way you can broadcast directly from windows service...without using scaleout feature of SignalR...

    Solution 1 (without using scaleout - preferred):

    Windows service connects to hub running inside the APS.NET app (hub1) as a client and calls special hub method which broadcasts message to all clients. OFC such method can be abused by normal (browser) clients. To eliminate this, you can create another hub (hub2) in ASP.NET app, place the method here and use GlobalHost.ConnectionManager.GetHubContext<hub1>() to broadcast to all clients connected to hub1. Hub2 can be protected by authorization so only Windows Service can use it. As you are already using DI container and injecting hubs into your business logic, it should be easy to define common interface (INotificationService) and create two different implementations - first will be used inside ASP.NET app (using Hub1 to do actual notification), second will be used inside Windows Service and use Hub2 to pass notification to ASP.NET app. From BL point of view, its the same thing...

    OFC for Win Service -> ASP.NET communication, you can use any other communication technology such as MVC or WebAPI (as @Pseudonym suggested), not just SignalR

    Solution 2

    If this is not solution for you for some reason, there is another idea. I think SignalR scaleout feature can be (mis)used here. Just host your hub1 both inside ASP.NET and Windows service (with different URL and port!). Even though clients will connect directly only to ASP.NET app, code running inside Windows Service will be still able to broadcast messages to them (messages are passed to scaleout message bus, then to ASP.NET app, then to clients).

    Things are more complicated using scaleout (need for SQL Server\Redis or any other SignalR backplane + latency etc etc) and you will probably want to lockout Windows service hubs so clients cannot connect to it directly and run hub1 methods (i'm not sure how to do it - one idea is to use another hub implementation but with the same name (HubNameAttribute) and empty methods + authorization so no one can connect to it). Anyway this is more trouble and you should have damn good reason to go this route...