SignalR and Joining Groups

2019-04-07 00:19发布

问题:

I am looking at SignalR for a project I am working on, and it seems to be EXACTLY what I want. However one bit that I am still a bit baffled by is the groups and joining.

I will try to describe the context of the implementation first. So a user within an existing system will want to hold a meeting about a given topic and will then create a room with a given name/identifier, they will then invite others into it and then it will basically be like a private chat room.

So the steps I assume would be as the host, create a room and join it, and then send out invites which would require users to click which would somehow tell the server which room to join into.

Now I see from the documentation that there is a Join and Disconnect method that you can hook into to put someone into a group, however it seems that the Join has no context associated with it other than the query string, so I am a bit confused as to what triggers a Join, as I would expect it would be a manually triggered method on the client passing over some object giving context as to what room to put them in, as you could have hundreds of private rooms.

So how do you give the Join method some context, and the disconnect one, so they know what room you are requesting to join, as if it is not manually triggered how can you set the query string, and if it is manually triggered why can you not send over a custom object. i.e

public Task Join()
{
    var groupName = Context.QueryString["some-room-identifier"];
    return Groups.Add(Context.ConnectionId, groupName);
}

vs

public Task Join(string groupName)
{
    return Groups.Add(Context.ConnectionId, groupName);
}

So am I missing something or is there some way to give context to a joining user to put them in the right place first time?

回答1:

I've had pretty much the same experience as you and have sort of worked/battled my way through it, so I'll share what I've done.

You'll need to capture a state somewhere. Check out the SignalR Hubs wiki https://github.com/SignalR/SignalR/wiki/Hubs under Roundtripping from Client to Server. I found that useful as it tells you how to set state on the server hub or client and retrieve it at the other end.

I came to same conclusion as you, that the Join is manually triggered by some event. I'm using a poll to see if anyone has requested a chat with the user. You can actually push from the server (see SignalR Join Group From Controller), meaning that the controller action that handles adding a new chat message can call the hub's Join method:

// join chatroom
public Task Join(dynamic mygroup)
{
var groupName = groupy.GetGroupName(parent.userId, (int)mygroup.userIdTo);
return Groups.Add(Context.ConnectionId, groupName);
}

For my group names, I use a Singleton to generate and keep track of names using a Dictionary<string, int[]> (the int[] is for userIds).

For the client state stuff, I ended up making a custom JavaScript object that managed the group name, like this...

Chat.Chatgroup = function (groupId, userIdTo) {
this.GroupId = groupId; // our group's title / id
this.UserIdTo = userIdTo; // who the other user is
}

Then I call the signalR method after connecting

onechat.getOurGroup(mygroup) // invoke method on server
.done(function (response) {
mygroup = response;
 /* + whatever else you need to do*/ });

Now you can set a state on the server and hold that state on the client:

public dynamic GetOurGroup(dynamic mygroup)
{
var ourId = groupy.GetGroupName(parent.userId, (int)mygroup.UserIdTo);
mygroup.GroupId = ourId;                    
return mygroup;
}

Hope it's at least vaguely helpful!