SignalR - 聊天的正确实现
SignalR - correct implementation of chat
我需要在我的网络项目上实现聊天功能。如何在一页上实现它 - 有很多关于它的文章。但我需要有能力:
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 对。当我删除此客户端代码时 - 不会调用该对。如何正确实现,通知其他用户,有人在线,但不需要每次都重新连接?
由于您在剃须刀 (_layout.cshtml) 页面中进行了 connect() 调用,因此您将在每个 post 返回(页面加载)时有效地 disconnecting/connecting。
您尝试使用的场景最适合 SPA(或 AJAX)场景,其中导航由客户端异步处理 JavaScript。您当前的设置是刷新屏幕、重新加载 JavaScript、重新 运行 文档 ready() 函数以及每个服务器呈现的导航。
另一种方法是使用客户端的实际用户 ID,并将其传递给 server.connect(id) 方法。然后使用这个用户 Id 来跟踪用户 activity 而不是 hub ConnectionId.
我需要在我的网络项目上实现聊天功能。如何在一页上实现它 - 有很多关于它的文章。但我需要有能力: 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 对。当我删除此客户端代码时 - 不会调用该对。如何正确实现,通知其他用户,有人在线,但不需要每次都重新连接?
由于您在剃须刀 (_layout.cshtml) 页面中进行了 connect() 调用,因此您将在每个 post 返回(页面加载)时有效地 disconnecting/connecting。
您尝试使用的场景最适合 SPA(或 AJAX)场景,其中导航由客户端异步处理 JavaScript。您当前的设置是刷新屏幕、重新加载 JavaScript、重新 运行 文档 ready() 函数以及每个服务器呈现的导航。
另一种方法是使用客户端的实际用户 ID,并将其传递给 server.connect(id) 方法。然后使用这个用户 Id 来跟踪用户 activity 而不是 hub ConnectionId.