在signalr中显示在线聊天用户。它将用户添加到列表中,但不会删除它们

时间:2016-08-30 20:42:59

标签: jquery asp.net-mvc signalr

我正在尝试使用MVC5SignalR中构建一个非常简单的聊天应用程序。

我在我的集​​线器类中创建了一个字符串列表,并添加了两个简单的方法来添加和删除元素,调用客户端以通过Jquery显示用户列表。

添加用户可以正常工作,但不会从列表中删除它们。知道为什么吗?

static List<string> users = new List<string>();

    public void AddUser(string name)
    {
        if (!users.Contains(name))
        {
            users.Add(name);
            Clients.All.updateUserList(users);
        }
        Clients.All.updateUserList(users);
    }
    public void RemoveUser(string name)
    {
        if (users.Contains(name))
        {
            users.Remove(name);
            Clients.All.updateUserList(users);
        }
        Clients.All.updateUserList(users);
    }
    public override System.Threading.Tasks.Task OnConnected()
    {            
        Clients.Caller.connected();
        return base.OnConnected();
    }
    public override System.Threading.Tasks.Task OnReconnected()
    {            
        Clients.Caller.connected();
        return base.OnReconnected();
    }
    public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
    {            
        Clients.Caller.disconnected();
        return base.OnDisconnected(stopCalled);
    }

在视图中

<script src="~/Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="~/signalr/hubs"></script>
<script>
    $(function () {
        var chat = $.connection.ChatHub;  

        chat.client.updateUserList = function (users) {
            var userList = $("#nameUsers");
            userList.empty();
            $.each(users, function (i) {
                var li = $('<li/>')
                    .text(users[i])
                    .appendTo(userList);                    
            });
        };

        chat.client.connected = function () {
            chat.server.addUser("@ViewBag.Username");
        };

        chat.client.disconnected = function () {
            chat.server.removeUser("@ViewBag.Username");
        }; ....

我从MVC中的ViewBag控制器获取用户名。

3 个答案:

答案 0 :(得分:1)

删除逻辑应该在OnDisconnected方法上进行。 Read this article from the SignalR documentation that explains lifetime events.

我们的想法是,您的客户端无法调用removeUser方法,因为它已经与服务器断开连接。

因此SignalR实现了OnDisconnected方法(您覆盖它,添加逻辑然后返回base.OnDisconnected),然后让服务器确定断开连接时间。

祝你好运!

答案 1 :(得分:0)

正如其他答案中所提到的 - 一旦客户端断开连接 - 它就无法调用服务器上的删除用户。更好的解决方案是:

static Dictionary<string, string> users = new List<string, string>();

private void AddUser(string connectionId, string name)
{
    lock (users)
    {
        users[connectionId] = name;
        Clients.All.updateUserList(users.Values.Distinct());
    }
}
private void RemoveUser(string connectionId)
{
    lock (users)
    {
        users.Remove(connectionId);
        Clients.All.updateUserList(users.Values.Distinct());
    }
}
public override System.Threading.Tasks.Task OnConnected()
{            
    AddUser(Context.ConnectionId, User.Identity.Name);
    return base.OnConnected();
}
public override System.Threading.Tasks.Task OnReconnected()
{            
    AddUser(Context.ConnectionId, User.Identity.Name);
    return base.OnReconnected();
}
public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
{            
    RemoveUser(Context.ConnectionId);
    return base.OnDisconnected(stopCalled);
}

主要差异:

  1. 避免信任服务器中心方法的客户端调用 - 然后你会遇到各种各样的问题......从网络问题到可能试图破坏你的系统的人
  2. 锁定用户异议 - 没有锁定你可能会腐败
  3. 通过connectionId键入用户,而不是用户名 - 这允许用户使用两个单独的浏览器/选项卡而不是搞砸事情(在以前的代码中,尝试登录两个选项卡,然后关闭一个看起来像两个用户都已注销)。
  4. 你的下一个问题是静态用户(这有点像黑客攻击),但相比之下,这是一个小问题。

答案 2 :(得分:0)

Connection is lost while removing user.You have to establish connection.

$.connection.hub.disconnected(function () {
        console.log("Disconnected. Reason: " + $.connection.hub.lastError.message); 
        setTimeout(function () {
            $.connection.hub.start();
        }, 5000); // Restart connection after 5 seconds.
    });

It will reestablish your connection.