首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从多个页面连接signalR集线器

从多个页面连接signalR集线器
EN

Stack Overflow用户
提问于 2014-08-10 14:05:43
回答 1查看 3K关注 0票数 3

在我的应用程序中,我需要从一个页面连接到signalR集线器,然后我希望重定向到另一个页面,并且仍然使用相同的signalR连接与服务器交互。如果我从一个页面Page1连接到signalR集线器,然后重定向到另一个页面,则来自Page1的聊天对象无效...

代码语言:javascript
复制
***var chat = $.connection.chatHub;
// Start the connection.
$.connection.hub.start().done(function () {});***

我还尝试在创建到signalR集线器的连接的页面中将聊天变量保存到sessionStorage,然后在另一个页面中恢复它,但没有成功……

有没有办法从Page1连接到signalR集线器,并从另一个页面使用相同的连接(使用相同的connectionID)?

EN

回答 1

Stack Overflow用户

发布于 2016-09-04 22:14:19

因此,如果我对您的问题的理解是正确的,那么当用户导航到另一个页面时,您希望能够保持相同的用户连接到您的signalr集线器。如果是这样,那么我想出了一个对我来说非常有效的解决方案。

以下是hub类中的方法:

代码语言:javascript
复制
private static List<UserViewModel> ConnectedUsers = new List<UserViewModel>();


/*
 * The 4 methods below handle user connection/disconnection
 */
public void Connect(string UserId)
{
    if(ConnectedUsers.Count(x => x.ConnectionId.Equals(Context.ConnectionId)) == 0)
    {
        if(ConnectedUsers.Count(x => x.UserId.Equals(UserId)) == 0)
        {
            var ConnectionId = Context.ConnectionId;
            ConnectedUsers.Add(new UserViewModel(UserId, ConnectionId));
        }
        else
        {
            SetConnection(UserId);
        }
    }
}

//This will be called when a user disconnects
public void Disconnect()
{
    var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId.Equals(Context.ConnectionId));
    if(item != null)
    {
        ConnectedUsers.Remove(item);
        //Update 
    }
}

//This method will handle when a user is assigned another ConnectionId
public void SetConnection(string UserId)
{
    if (ConnectedUsers.Count(x => x.UserId.Equals(UserId)) != 0)
    {
        UserViewModel Existing = ConnectedUsers.FirstOrDefault(x => x.UserId.Equals(UserId));
        ConnectedUsers.Remove(Existing);
        Existing.ConnectionId = Context.ConnectionId;
        ConnectedUsers.Add(Existing);
    }
    else
    {
        Connect(UserId);
    }
}

/*
This gets called every time a user navigates to another page, 
but if they stay on the site then their connection will be reset 
and if they go off site then their connection will be terminated and reset
the next time the log back into the site
*/
public override Task OnDisconnected(bool stopCalled)
{
    Disconnect();
    return base.OnDisconnected(stopCalled);
}

在您的应用程序中,您需要为用户分配一个唯一的静态ID或GUID,该ID或GUID可以与ViewModel配对:

代码语言:javascript
复制
public class UserViewModel
{
    public string UserId { get; set; }
    public string ConnectionId { get; set; }

    public UserViewModel() { }
    public UserViewModel(string UserId, string ConnectionId)
    {
        this.UserId = UserId;
        this.ConnectionId = ConnectionId;
    }
}

connection方法将在用户连接时进行处理。首先,它将查看连接的用户是否已包含在ConnectedUsers列表中,并通过根据用户的ConnectionId和UserId查找用户来实现这一点。如果它们不存在,则将它们添加到列表中,但如果它们确实存在,则转到SetConnection方法。

在SetConnection方法中,我们获得一个UserId并进行查找,以确保列表中存在一个现有用户。如果我们找到一个现有的用户,那么我们将他们从列表中删除,更新他们的连接id,然后将他们放回列表中。这有助于确保计数具有正确的用户数。您将注意到,在SetConnection方法中有一个对Connect的调用,稍后我将对此进行说明。

接下来是Disconnect方法。它将根据用户的UserId在ConnectedUser列表中查找用户(这一点很重要,因为它将始终保持不变)并删除他们。此方法将在用户注销时调用,或者由我们的OnDisconnect方法调用。

您可以看到我已经覆盖了OnDisconnect方法。每当用户导航到站点上的另一个页面或完全离开站点时,都会调用此方法(稍后将对此进行详细介绍)。

现在我们可以检查我们的JS了:

代码语言:javascript
复制
$(document).ready(function () {
    var shub = $.connection.securityHub;
    $.connection.hub.start().done(function () {
        Connect(shub);
    });

    //Client calls here
});

//Server calls here

function Connect(shub) {
    var id = $('#unique-user-id').attr('data-uid');

    if (Cookies.get('Connected') == null) {
        Cookies.set('Connected', 'UserConnected', { path: '' });
        shub.server.connect(id);;
    }
    else {
        shub.server.setConnection(id);
    }
}

function Disconnect() {
    Cookies.remove('Connected', { path: '' });
    $.connection.securityHub.server.disconnect();
}

请确保在母版页或_Layout.cshtml中添加了一个脚本标记,并引用了此标记,因为这将需要在站点的每个页面上运行。在连接部分,它将在每次加载页面时启动hub,这也将在$(document).ready外部调用我们的$(document).ready方法。

Connect方法以集线器为参数,它将找到我在页面上设置的惟一ID ($('#unique-user-id')是我的_Layout中的一个元素,因此每个页面都会有它,但您可以按您想要的任何方式传递UserId )。然后,它将查找一个我称之为已连接的cookie。此cookie将在会话到期时过期,因此如果他们要关闭选项卡或浏览器,则连接的cookie将消失。如果cookie为空,则设置cookie并运行Hub.cs中的Connect方法。如果ConnectionId已经存在,那么我们将运行SetConnection方法,以便现有用户可以获得新的cookie。

我已经包含了一个Disconnect方法,它可以在您需要的时候触发。一旦您的注销按钮已被单击,然后您可以运行disconnect方法,它将删除cookie并断开您与服务器的连接。

现在我想谈谈Connect和OnDisconnect方法。每当用户导航到站点上的另一页、关闭浏览器或退出站点的选项卡时,都会运行此方法。这意味着每次用户导航到您站点上的另一个页面时,他们都会断开连接(但他们连接的cookie将保持正常状态,因为如果他们转到另一个页面,我们的JS方法都没有被调用,所以我们没有删除他们的cookie)。一旦页面加载,我们的JS就开始发挥作用,$(document).ready就会运行,然后再运行。它将启动集线器,然后运行JS Connect方法,该方法将查看Connect cookie是否存在,并在服务器上运行SetConnection方法,然后该方法将查找当前连接的用户,并在我们的列表中为他们提供一个新的ConnectionId。

唯一奇怪的是,如果您显示一个已连接用户的列表,当他们转到其他页面时,这些用户将闪烁。我的意思是,假设您只在div或其他文件中显示用户计数(ConnectedUsers.Count)。假设您有5个已连接的用户,其中一个用户导航到另一个页面,计数将短暂到4(因为OnDisconnect方法将运行),然后返回到5(因为JS调用Connect方法)。

您可以做的不同的一件事是,不像我这样通过JS传递UserId,在Hub.cs类中,您可以像这样获得UserId:Context.User.Identity.GetUserId(),这可能比将其作为页面上的数据属性更好。如果您想这样做,请确保使用:using Microsoft.AspNet.Identity将其包括在内。这就是我决定要做的事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25226041

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档