1

I need to implement some push notfications for my asp.net core 2.2 site. I found signalr, and started looking at it. I have tried implementing a small toy example, and I now have a hub class that looks as so:

As simple as can be. I now have a controller from which I need to trigger a push notification on the client computer. which could be triggered by thus controller being hit (In my real project, I need to send a push notification when a user is online, and when a new article is published on my site). So here is my controller:

public class msgController : Controller
{
public IActionResult Index()
{
return Content("serving content");
}
}

But I now need to somehow trigger my hub's sendMessage function. I'm able to call it if I just put the hub inside the controller, like this:

public class msgController : Controller
{
private IHubContext<NotificationHub> _hub;
public msgController(IHubContext<NotificationHub> hub)
{
_hub = hub;
}
public IActionResult Index()
{
_hub.Clients.All.SendAsync("ReceiveMessage", "bruger", "besked");
return Content("serving content");
}
}

But I would like to use my actual Hub class, and also, none of the docs that I can find do it like this. How could I do this?

I've seen some places giving answers that does'nt really make a lot of sense to me, like just accessing the contexthub, through a GlobalHost, that is'nt available to me. Other places claim that this just is'nt possible.

So how do I call/trigger my hub, and send a message to the client? Also, the version of my site where the hub is just written in the controller works now, and a sendmesage() function is called. But I can't really see the message being sent clientside. Where can I find it?

  • GlobalHost is not available in .net core, this is a .net full signalR version. What's wrong with IHubContext injection? this is exactly the way to do what you want. – Maxim Zabolotskikh Jun 21 '21 at 08:51
  • hmm, it's because I want my hub to contain all the other methods assoicated with the hub. Things like onconnected and so on – BinaryGarste Jun 21 '21 at 09:25
  • Also I want to define my own functions in my hub class – BinaryGarste Jun 21 '21 at 10:24
  • Well, you simply can't get the Hub without the HubContext. Go with the answer by @Kiril1512 or wrap your hub in another class (inject it with HubContext). Add to the wrapper the methods you need and than use the wrapper everywhere. – Maxim Zabolotskikh Jun 21 '21 at 14:08

1 Answers1

3

You just need to declare an interface with your hub methods like:

public interface ISignalRHub
{
    /// <summary>
    /// Broadcasts the chart data.
    /// </summary>
    /// <param name="chartData">The chart data.</param>
    Task BroadcastChartData(List<ChartModel> chartData);

    /// <summary>
    /// Broadcasts the message.
    /// </summary>
    /// <param name="message">The message.</param>
    Task BroadcastMessage(string message);

    /// <summary>
    /// Broadcasts the message.
    /// </summary>
    /// <param name="message">The chat message.</param>
    Task BroadcastMessage(ChatMessage message);
}

and define it in the hub:

public class SignalRHub : Hub<ISignalRHub>

then after injecting it in the controller:

public msgController(IHubContext<SignalRHub, ISignalRHub> hub)
{
  _hub = hub;
}

So if you want send a message to client just create a method in the hub and declare it in your interface. Because with IHubContext you can't directly call a specific hub method or client.

As said in the Microsoft documentation:

When client methods are called from outside of the Hub class, there's no caller associated with the invocation. Therefore, there's no access to the ConnectionId, Caller, and Others properties.

Kiril1512
  • 3,231
  • 3
  • 16
  • 41
  • You can see this signalr example project, soon I will add an push notifications example: https://github.com/Kiril1512/SignalRDemo – Kiril1512 Jun 21 '21 at 14:04
  • really cool project! There is one thing though. I can't seem to figure out where the sending of messages actually happens? I can find the hub class, but I can't find anywhere where it seems like the message is sent – BinaryGarste Jun 23 '21 at 15:30
  • On the worked example it happens with `await this.hub.Clients.All.BroadcastChartData(DataManager.GetData());` so in the client side there is a signalR listner that is listening on the method like: `private addMessageListener = () => { this.hubConnection.on('BroadcastMessage', (message: Message) => { this.message = message; this.messages.push(this.message); console.log(message); }); }` – Kiril1512 Jun 23 '21 at 15:34