【问题标题】:SignalR - Send message to All, Excluding a user's all connectionsSignalR - 向所有人发送消息,排除用户的所有连接
【发布时间】:2014-01-11 23:07:26
【问题描述】:

在我的 ASP.NET 4.5 WebForms 项目中,我正在向当前连接的所有客户端发送更新通知。我有两个 Hub,其中一个向用户的其他打开的选项卡或窗口发送更新通知,另一个向其他人发送更新通知。

第一个枢纽是这样的

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

在这里,我添加了由会员用户创建的所有 connectionId(来自每个创建的连接用户 - 选项卡、窗口...),并将通知发送到除呼叫者之外的所有这些 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。这样就可以了(我认为)。

我想我能说出我需要什么。我怎样才能不费力地完成那个场景?

谢谢!

【问题讨论】:

  • 似乎你最好使用一个包含“self”和“others”方法的集线器。
  • 好吧,假设我合并了两个集线器,不改变“其他集线器”的通知方式,什么都不会改变。你有什么建议?

标签: c# asp.net notifications signalr


【解决方案1】:

您应该更改您的Groups 集合以使用name 作为键和一个列表作为值。

然后更改您的OnConnected() 覆盖以查找name 键并添加或创建connectionIdList<string>

在您的“自我”集线器方法中,您希望所有连接都与当前用户相关联:

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

【讨论】:

  • 这看起来很有趣。现在试一试。很快就会更新。
  • 将 Groups 设为字典,然后它就会拥有它
  • 我添加了一些代码。希望没有太多错误:)。这里有一些不错的文档:asp.net/signalr/overview/signalr-20/hubs-api/…。 Groups('name', connectionId) 也可能有用,但同样,您需要以某种方式维护它们。
  • 我认为重要的是要意识到 SignalR 无法让您查看哪些用户属于哪个组,您必须自己跟踪。这就是 mrtig 建议您创建字典的原因。
  • @ilter 您应该包含 using System.Collections.Generic;using System.Linq; 以便使用 .Where 扩展。
猜你喜欢
  • 1970-01-01
  • 2013-03-19
  • 2019-08-04
  • 2020-09-09
  • 1970-01-01
  • 2014-09-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多