防止在线用户列表信号器中的重复用户

时间:2015-10-09 06:40:11

标签: asp.net-mvc signalr

我正在开发在线用户列表。我的代码是:

public class User
    {
        public string id;
        public string name;
        public string dpExtension;
    }
    public class OnlineUsers : Hub
    {
        private Entities db = new Entities();
        public static ConcurrentDictionary<string, User> users = new ConcurrentDictionary<string, User>();
        public override System.Threading.Tasks.Task OnConnected()
        {
            User u = new User();
            u.id = "visitor";
            u.name = "Visitor";
            u.dpExtension = "";
            if (Context.User.Identity.IsAuthenticated)
            {
                u.id = Context.User.Identity.GetUserId();
                var da = db.AspNetUsers.Find(u.id);
                u.name = da.Email;
                u.dpExtension = da.dpExtension;
            }
            User abc;
            var data = users.TryGetValue(Context.ConnectionId, out abc); 
            if (!data)
            {
                users.TryAdd(Context.ConnectionId, u);
            }
            Clients.All.showConnected(users);
            return base.OnConnected();
        }
        public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
        {
            User abc;
            users.TryRemove(Context.ConnectionId, out abc);
            Clients.All.showConnected(users);
            return base.OnDisconnected(stopCalled);
        }
    }

现在,如果用户打开了一个浏览器标签,则会在列表中显示一次,这很好。但是,如果用户打开两个选项卡,它将在列表中显示两次。如何在列表中只显示一个用户一次?

1 个答案:

答案 0 :(得分:0)

您需要将ConnectionIds映射到一个用户。您可以在本文中阅读很多内容 - http://www.asp.net/signalr/overview/guide-to-the-api/mapping-users-to-connections

我在您的代码中添加了一些内容,您可以看到本文中发生了什么:

public class User
{
    public string dpExtension;
    public string id;
    public string name;
}

public class Map
{
    public string UserId { get; set; }
    public User User { get; set; }
    public List<string> Connections { get; set; }
}

public class OnlineUsers : Hub
{
    public static readonly List<Map> maps = new List<Map>();
    private readonly Entities db = new Entities();

    public override Task OnConnected()
    {
        var user = new User { id = "visitor", name = "Visitor", dpExtension = "" };

        if (Context.User.Identity.IsAuthenticated)
        {
            user.id = Context.User.Identity.GetUserId();
            var da = db.AspNetUsers.Find(user.id);
            user.name = da.Email;
            user.dpExtension = da.dpExtension;
        }

        Map data = maps.FirstOrDefault(t => t.UserId == user.id);
        if (data == null)
        {
            maps.Add(new Map() {
                UserId = user.id,
                User = user,
                Connections = new List<string>() { Context.ConnectionId }
            });
        }
        else
        {
            data.Connections.Add(Context.ConnectionId);
        }

        Clients.All.showConnected(maps.Select(m => m.User));
        return base.OnConnected();
    }

    public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
    {
        var map = maps.FirstOrDefault(t => t.Connections.Contains(Context.ConnectionId));
        if (map != null)
        {
            map.Connections.Remove(Context.ConnectionId);
            if (map.Connections.Count <= 0)
            {
                maps.Remove(map);
            }
        }

        Clients.All.showConnected(maps.Select(m => m.User));
        return base.OnDisconnected(stopCalled);
    }
}