我正在开发在线用户列表。我的代码是:
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);
}
}
现在,如果用户打开了一个浏览器标签,则会在列表中显示一次,这很好。但是,如果用户打开两个选项卡,它将在列表中显示两次。如何在列表中只显示一个用户一次?
答案 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);
}
}