Signalr 浏览器刷新时信号器加入组新建Context.ConnectionId

Signalr 浏览器刷新时信号器加入组新建Context.ConnectionId,signalr,Signalr,我的应用程序有很多用户组 有一个管理员页面,可以向这些用户组中的一个或多个发送通知 我有一个中心,管理员可以在通过对WebAPI方法的AJAX调用将通知保存到数据库后将其发布到该中心。当这在Ajax成功部分返回时,我调用服务器中心上的一个方法,该方法将通知实时发布到一个或多个组。这些组由int数组表示,该数组通过使用.ToString()转换int来创建组名 客户端的主页上有一个小部件,显示通知。一些用户可以是多个用户组的一部分,但他们在页面顶部有一个下拉列表,用于指定他们当前正在查看的用户组。

我的应用程序有很多用户组

有一个管理员页面,可以向这些用户组中的一个或多个发送通知

我有一个中心,管理员可以在通过对WebAPI方法的AJAX调用将通知保存到数据库后将其发布到该中心。当这在Ajax成功部分返回时,我调用服务器中心上的一个方法,该方法将通知实时发布到一个或多个组。这些组由int数组表示,该数组通过使用.ToString()转换int来创建组名

客户端的主页上有一个小部件,显示通知。一些用户可以是多个用户组的一部分,但他们在页面顶部有一个下拉列表,用于指定他们当前正在查看的用户组。因此,它们可能是许多用户组的一部分,但一次只能查看1个

因此,我想我会喜欢Jabbr聊天室,但我不想设置太多,因为这个应用有不同的意图。因此,当客户端登录时,它们会根据dropdownlist中所选项目的值加入一个组。我确实注意到,每当我作为客户端刷新页面时,都会使用新的connectionId再次调用“Join”服务器方法。是这样吗?我不想有比实际更多的联系。我还需要断开客户机与组的连接,并在他们更改dropdownlist时将其重新加入到新组

我正在寻找演示,但发现要么是非常简单的演示,要么是非常复杂的演示,我最初的目标是介于两者之间的东西,因为我打算在网站的其他区域添加信号器功能,所以不想太多地锁定我的对象模型

因此,在我的中心,我得到:

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

public void SendNotificationsToGroups(string title, string description, int[] groups) {
        foreach (int i in groups) {
            Clients.OthersInGroup(i.ToString()).addMessage(Title, description);
        }
}
管理页面调用SendNotificationsToGroups,这可以正常工作。正如您所看到的,它传递一个int数组,int是要向其广播通知的组。我只需要.ToString int来创建组名

客户机执行以下操作:

var Hub = $.connection.myHub;

Hub.client.addMessage = function (title, description) {
  $('#Notification').find('tr:first').before('<tr><td>'+title+description'</td></tr>');
}

$.connection.hub.start().done(function () {
    var groupId = $('#userGroupID').val();
    newsHub.server.join(groupId);
}
var-Hub=$.connection.myHub;
Hub.client.addMessage=函数(标题、说明){
$(“#通知”).find('tr:first')。在(''+标题+说明'')之前;
}
$.connection.hub.start().done(函数(){
var groupId=$('#userGroupID').val();
newsHub.server.join(groupId);
}
我主要关心的是addMessage部分工作时的连接方法!!管理员发送通知,客户端看到它们。问题是客户端刷新浏览器时,服务器上会再次调用连接(我在上面设置了断点)它有一个新的Context.ConnectionId。这是坏的吗?这会导致连接过多吗?是否有一个javascript/jQuery调用,我应该执行该调用以确保连接在关闭窗口或客户端离开页面时被破坏,那么浏览器刷新问题呢

谢谢你的建议。

signar,但它是通过一条异步消息来实现的,因此它可能不会立即发生。此外,服务器端将自动检测并清除“死”连接,作为其内部管理工作的一部分


也就是说,如果可以的话,最好保持SignalR连接处于活动状态,而不是在每个页面导航上断开/重新连接。不断断开和重新连接有点达不到目的,而且很明显在页面导航之间可能会丢失一些消息。

我解决问题的方法是存储用户的会话和连接一对多用户表中的tionId。例如,您可以创建一个PersonSession表,其中存储上述信息以及其他信息,如主机、连接时间、断开连接时间和用户代理

您可以使用以下代码在
OnConnected()
方法上获取会话:

var session = Context.RequestCookies.ContainsKey("ASP.NET_SessionId") ? Context.RequestCookies["ASP.NET_SessionId"].Value : null;
OnDisconnected()
方法中,您只需使用DisconnectTiemstamp更新此记录

然后,当它们刷新时,您可以检查以前的记录(我在任何时候为一个用户保留最多3条记录),以查看它们是否具有相同的会话,如果它们具有相同的会话,则您不进行更新,否则,您假设这是一个新会话并进行更新

if (session != null)
{
     var MyInActiveSessions = p.PersonSessions.Where(x=>x.DisconnectTimestamp != null);
                            bUpdateStatus = !MyInActiveSessions.Any(x => x.SessionID != null &&          x.SessionID == session);
}
此外,请记住,您必须在登录时强制重新生成会话cookie,因为ASP.net即使在您注销时也会保留旧的会话cookie。为此,您需要执行以下几项操作:

  • 在登录代码中,将任意随机值放入会话变量,以强制ASP.NET生成cookie(例如,
    Session['0']=0;
  • 在注销代码中,放弃会话并将cookie添加到响应:

    Session.放弃();
    Response.Cookies.Add(新的HttpCookie(“ASP.NET_SessionId”);

  • 最后,在Web.config中,确保会话自动重新生成:

  • 希望这能有所帮助。

    想详细说明一下您是如何做到这一点的吗(防止刷新之间的connectionId循环)?谢谢我真的不知道您的应用程序的确切上下文,但一种方法是转向现代的单页应用程序(SPA)当SPA启动时连接信号器连接,然后您可以根据需要动态加载应用程序的各个部分。