【问题标题】:SignalR - correct implementation of chatSignalR - 聊天的正确实现
【发布时间】:2017-07-24 18:57:19
【问题描述】:

我需要在我的网络项目中实现聊天。如何在一页上实现它 - 有很多关于它的文章。但我需要有能力: 1. 通知其他用户有人登录网站(在任何页面上,不仅在聊天页面上) 2. 通知其他用户有人退出

所以,我有以下集线器代码:

    public void Connect()
    {
        try
        {
            var id = Context.ConnectionId;
            string username = Context.User.Identity.Name;

            var currentUser = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
            if (currentUser == null)
            {
                AddNewUserToCollection();
            }
            else
            {
                // update ConnectionId for sure (connection id is changed sometimes (probably if user is logged out and login again))
                if (currentUser.ConnectionId != id)
                {
                    var companyId = _chatRepository.GetCompanyIdOfUser(username); // throws exception if companyId is null
                    Groups.Remove(currentUser.ConnectionId, companyId.ToString());
                    Groups.Add(id, companyId.ToString());
                    currentUser.ConnectionId = id;
                    //Clients.Group(companyId.ToString()).onNewUserConnected(username);
                }
            }
        }
        catch(InvalidCompanyException c_ex)
        {
            Clients.Client(Context.ConnectionId).onErrorMessage($"User '{c_ex.Username}' does not exist");
        }
    }


    public void Disconnect()
    {
        string username = Context.User.Identity.Name;
        var item = connectedUsers.Where(p => p.Username == username).FirstOrDefault();
        if (item != null)
        {
            connectedUsers.Remove(item);
            Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
            Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
        }
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        var item = connectedUsers.Where(p => p.ConnectionId == Context.ConnectionId).FirstOrDefault();
        if (item != null)
        {
            connectedUsers.Remove(item);
            Groups.Remove(item.ConnectionId, item.CompanyID.ToString());
            Clients.Group(item.CompanyID.ToString()).onUserDisconnected(item.Username);
        }
        return base.OnDisconnected(stopCalled);
    }

我在 _layout.cshtml 中添加了以下代码:

    <script>
        $(document).ready(function () {
            var chat = $.connection.chatHub;

            $.connection.hub.start().done(function () {
                chat.server.connect();
            });
        });
    </script>

通知其他用户当前用户已登录。但是调试器说,当用户使用不同的 connectionId 重新加载页面(通过页面)时,每次都会调用该对 OnDisconnected/Connect。当我删除此客户端代码时-不会调用该对。如何正确实现,通知其他用户有人在线,但无需每次都重新连接?

【问题讨论】:

  • 最基本的版本就差不多了。我所建议的只是在有人断开连接后等待几秒钟,然后再告诉其他人他们已经断开连接(只有在用户没有出现新连接 ID 的情况下)。您的下一个问题是与打开多个选项卡的用户打交道(您需要跟踪每个用户拥有的连接数)。仅供参考,理想情况下这是在集线器管道中,但您可能应该先在这里工作。跨度>

标签: signalr signalr-hub signalr.client signalr-2


【解决方案1】:

由于您在 razor (_layout.cshtml) 页面中有 connect() 调用,因此您将在每次回发(页面加载)时有效地断开/连接。

您尝试使用的场景最适合 SPA(或 AJAX)场景,其中导航由客户端 JavaScript 异步处理。您当前的设置是刷新屏幕、重新加载 JavaScript、使用每个服务器呈现的导航重新运行文档 ready() 函数。

另一种选择是使用客户端的实际用户 ID,并将其传递给 server.connect(id) 方法。然后使用此用户 ID 来跟踪用户活动,而不是使用集线器 ConnectionId。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 2015-02-23
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多