SignalR 聊天成员不会在聊天中获得现有用户数组

SignalR chat members don't get existing array of users in chat

SignalR 聊天 - 基于:

我正在尝试维护聊天中已连接的人员列表。它是 'user' 对象的列表,用户对象是存储 'name' 及其分配的 'color'(文本的红色、蓝色或绿色等颜色)

的容器

因此服务器模型是一个具有 List 成员的对象:

public class GroupMemberModel
{
    [JsonProperty("name")]
    public string UserName { get; set; }

    [JsonProperty("color")]
    public string Color { get; set; }

    [JsonProperty("avatar")]
    public string AvatarImagePath { get; set; }
}

public class MessageModel
{
    [JsonProperty("message")]
    public string Message { get; set; }

    [JsonProperty("user")]
    public GroupMemberModel User { get; set; }

    [JsonProperty("group")]
    public List<GroupMemberModel> ChatGroup { get; set; }
}

然后当用户发送消息时,服务器检查这个新用户是否在列表中,如果不在则添加:

    public void Send(MessageModel clientModel)
    {
        if (!clientModel.ChatGroup.Contains(clientModel.User))
        {
            clientModel.ChatGroup.Add(clientModel.User);
            clientModel.ChatGroup.Sort();
        }
        // Call the broadcastMessage method to update clients.
        Clients.All.broadcastMessage(clientModel);
    }

我的问题是,每当有新用户加入时,他们的 GroupMemberModel 用户 ChatGroup 列表的初始 'knowledge' 是空的。所以当一个新用户加入时,'participants' 总是替换为刚刚加入的单个用户......这也发生在已经在聊天的用户之间 - 最后一个留言的人是唯一的人'Participants' 列表.. 所以这个列表根本没有被维护。

所以每次调用服务器serverHub 'send' 函数时,是否需要序列化/反序列化MessageModel 的List ChatGroup 成员?

我认为 SignalR 会以某种方式管理服务器上的对象而不会影响存储机制?我猜它们对于每个服务器调用都是唯一的,这就是为什么它们对每个用户都是空的?嗯 - 也许列表必须是静态的?

SignalR 在其自己的组结构中对用户进行内部管理。您不能直接访问它,只能通过他们提供的一些访问器访问,但这些访问器不会执行您想要的操作。

我做了非常相似的事情。

对于列表,我使用了 static 字典。它必须是 staticSingleton 因为每个连接都会创建一个新的集线器。 Hub 就像一个网页,当客户端连接时创建一个新实例,当它们断开连接时销毁。 Hub 的任何局部变量都用它创建和销毁。

static readonly ConcurrentDictionary<string, GroupMemberModel> Members; // string is the connection ID that is unique for every connection

Hub 中,我为 OnConnectOnDisconnectOnReconnect 添加了重载,用于检查用户是否存在并添加或删除用户来自 Members 列表。每个方法都有一个 Context 对象,其中包含可用于添加或删除成员的已连接客户端的数据。

例如:

public override Task OnConnected()
{
    AddNewMember(); // add member to list, here you can check any security, header, etc.
    // Note: Context contains the connected member

    return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
    var member = GetMember();
    if (member != null)
    {
        Members.TryRemove(member.ConnectionId, out _);
    }

    return base.OnDisconnected(stopCalled);
}
public override Task OnReconnected()
{
    var member = GetMember(); // find the connection in the list
    if (item == member)
    {
        var user = AddNewMember();
    }

    return base.OnReconnected();
}

这样,您的服务器将始终维护一个连接成员列表。