从多个页面连接signalR hub

时间:2014-08-10 06:05:43

标签: signalr

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

***var chat = $.connection.chatHub;
// Start the connection.
$.connection.hub.start().done(function () {});***

我还尝试将chat变量保存到创建与signalR hub连接的页面中的sessionStorage,然后在其他页面中将其恢复,但没有成功......

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

1 个答案:

答案 0 :(得分:2)

因此,如果我正确理解您的问题,那么您希望能够在导航到其他页面时让同一用户连接到您的信号器中心。如果是这样,那么我想出了一个对我来说非常好的解决方案。

以下是集线器类中的方法:

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);
}

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

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;
    }
}

连接方法将在用户连接时进行处理。首先,它将查看ConnectedUsers列表中是否已包含已连接的用户,并通过ConnectionId及其UserId查找用户来实现此目的。如果它们不存在则会将它们添加到列表中,但如果它们存在,那么我们将转到SetConnection方法。

在SetConnection方法中,我们得到一个UserId,我们进行查找以确保列表中有现有用户。如果我们找到现有用户,那么我们将其从列表中删除,更新其连接ID,然后将它们放回列表中。这有助于确保Count具有正确数量的用户。你会注意到在SetConnection方法中有一个对Connect的调用,稍后我会解释。

接下来是Disconnect方法。它将通过UserId在ConnectedUser列表中查找用户(这很重要,因为它始终保持不变)并删除它们。当用户通过我们的OnDisconnect方法注销OR时,将调用此方法。

OnDisconnect方法是您可以看到我已覆盖的方法。只要用户导航到您网站上的其他网页或完全离开网站,就会调用此方法(稍后会详细介绍)。

现在我们可以检查一下JS:

$(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并引用此标记,因为这需要在您网站的每个页面上运行。在$(document).ready部分,每次加载页面时都会启动集线器,这也会在$(document).ready之外调用我们的连接方法。

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

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

现在是我想谈谈Connect和OnDisconnect方法的时候了。这是一种在用户导航到您网站上的其他页面,关闭其浏览器或退出您的网站标签时运行的方法。这意味着每次用户导航到您网站上的另一个页面时,他们将首先断开连接(但他们的Connected cookie将保持原状,因为如果他们转到另一个页面,我们的JS方法都没有被调用,所以我们没有删除他们的曲奇饼)。一旦页面加载我们的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。这就是我决定这样做的方式。

相关问题