在我的ASP.NET 4.5 WebForms项目中,我正在向当前连接的所有客户端发送更新通知。我所拥有的是两个集线器,其中一个向用户的其他打开的选项卡或窗口发送更新通知,另一个是向其他人发送更新通知。
第一个集线器就像
[Authorize]
public class SelfNotificationHub : Hub
{
public void ShowSelfNotification(string page, string type, int id, string title)
{
string username = Context.User.Identity.Name;
Clients.OthersInGroup(username).broadcastNotification(page, type, id, title);
}
public override Task OnConnected()
{
string name = Context.User.Identity.Name;
Groups.Add(Context.ConnectionId, name);
return base.OnConnected();
}
}
这里我将添加由成员资格用户创建的所有connectionIds(来自每个创建的连接用户 - 制表符,窗口......),并将通知发送给除调用者之外的所有这些ID。来电者的通知由js代码显示。
另一个中心就像
[Authorize]
public class NotificationHub : Hub
{
public void ShowNotification(string page, string type, int id, string title)
{
string username = Context.User.Identity.Name;
Clients.Others.broadcastNotification(username, page, type, id, title);
}
}
在此我发送通知,包括用户名以通知其他用户。
问题是,通过此配置,用户的其他打开的选项卡和窗口正在接收来自两个集线器的通知。在第二个中心,我不能一起排除用户的connectionIds,如Clients.AllExcept(username)
。 AllExcept函数需要类型“String [] ConnectionIds”,我无法弄清楚如何获取组中的connectionIds。这样,我可以从单个用户的组创建一个String []数组,并从该数组中排除callerId。这样做(我认为)。
我想我可以告诉我需要什么。如何在没有任何麻烦的情况下完成这种情况?
谢谢!
答案 0 :(得分:4)
您应该更改Groups
集合,以使用name
作为键,将List作为值。
然后更改您的OnConnected()
覆盖以查找name
密钥,并添加或创建List<string>
connectionId
。
在“自我”中心方法中,您需要与当前用户关联的所有连接:
List<string> clientWindows;
Groups.TryGetValue(name, out clientWindows);
clientWindows.ForEach(connectionId => {
Clients.Client(connectionId)
.broadcastNotification(username, page, type, id, title);
});
在您的“其他”中心方法中,您需要获取所有连接列表,但与该客户端名称关联的连接除外:
var others = Groups.Where(n => n.Key != name).SelectMany(s => s.Value);
Clients.AllExcept(others.ToArray())
.broadcastNotification(username, page, type, id, title);
修改强> 这个答案假设Groups是一个全局定义的静态字典。
Dictionary<string, List<string>> Groups = new Dictionary<string, List<string>>()
要使其适应IGroupManager组,您需要创建静态字典以维护与用户关联的连接列表。这是代码:
using System.Collections.Generic;
using System.Linq;
private static Dictionary<string, List<string>> userGroups
= new Dictionary<string, List<string>>()
private static object _lock = new object();
public class NotificationHub : Hub
{
public void ShowSelfNotification(string page, string type, int id, string title)
{
string username = Context.User.Identity.Name;
Clients.Group(username).broadcastNotification(page, type, id, title);
}
public void ShowNotification(string page, string type, int id, string title)
{
string username = Context.User.Identity.Name;
var others = userGroups.Where(n => n.Key != username)
.SelectMany(s => s.Value);
Clients.AllExcept(others.ToArray())
.broadcastNotification(username, page, type, id, title);
}
public override Task OnConnected()
{
string name = Context.User.Identity.Name;
Groups.Add(Context.ConnectionId, name);
lock(_lock)
{
if (userGroups .ContainsKey(name))
userGroups [name].Add(Context.ConnectionId);
else
userGroups .Add(name, new List<string>{Context.ConnectionId})
}
return base.OnConnected();
}
public override Task OnDisconnected()
{
string name = Context.User.Identity.Name;
lock(_lock)
{
if (userGroups .ContainsKey(name))
userGroups[name].Remove(Context.ConnectionId);
}
return base.OnDisconnected();
}
}