Find SignalR client by ID in its context

Viewed 297

So I want to send a message to a specific client via SignalR. That client is not Clients.Caller - currently I can only identify it by let's call it "ID", a property in the context: this.Context.Items["ID"]

So to find a client by its ID, how do I...access all clients or contexts? Or should I save this ID in a different way? This is not the connection ID, it is an ID that maps to something in the database.

Basically I'd like to go Clients.Single(c => c.Items["ID"] == specificId).SendMessage(msg);

2 Answers

In the OnConnectedAsync method in your hub, you can group a user by their "ID" each time they connect.

E.G:

public async override Task OnConnectedAsync()
{
    var currentUserId = /*get your current users id here*/
    await Groups.AddToGroupAsync(Context.ConnectionId, $"user-{currentUserId}");
    await base.OnConnectedAsync();
}

Then when you need to send that person a message, you can just broadcast it to their 'personal' group. (One person may have multiple connections, so the group approach work perfectly for us).

E.G:

Clients.Group($"user-{userId}").SendAsync("UserSpecificMessage", message);

When users disconnect, SignalR will handle the removing of connections from the groups automatically.

In using this approach, we do not have to unnecessarily broadcast a message to every single client with the intention of only one client filtering out the message based on the id.

You can send the ID down to the clients using context.Clients.User(...) or context.Clients.All(). Then in JavaScript, read the ID and compare it to what's on the page. If it's a match, carry out some action; else ignore.

As an example, let's say your app's processing a specific record on an edit screen. The record ID is on the page as a form field. You send a SignalR message down from C# with the ID. You do a comparison in JavaScript between the ID and the form field value; if they match, you display a toaster message, perform other processing, etc.

Related