Asp.net core 如何将消息发送到保存在AspNetUsers表Signal R中的用户id

Asp.net core 如何将消息发送到保存在AspNetUsers表Signal R中的用户id,asp.net-core,signalr,signalr-hub,Asp.net Core,Signalr,Signalr Hub,我在试着发个信息。我已尝试使用连接id public Task SendMessaageToConnectionID(string ConnectionID,string Message) { return Clients.Clients(ConnectionID).SendAsync("RecieveMessage", Message); } 这是成功的 现在我正在尝试这个 public Task SendMessageToUser(string userId,string Mess

我在试着发个信息。我已尝试使用连接id

public Task SendMessaageToConnectionID(string ConnectionID,string Message)
{
    return Clients.Clients(ConnectionID).SendAsync("RecieveMessage", Message);
}
这是成功的 现在我正在尝试这个

public Task SendMessageToUser(string userId,string Message)
{
    return Clients.Clients(userId).SendAsync(Message);
}
我正在发送保存在AspNetUser表中的用户的用户id

How Can I send this to a User ID or is there any other way except connection id to send the message to user?

SignalR不会为我们存储
用户ID
-
连接ID
映射。我们需要自己去做。例如,当一些用户设置到集线器的连接时,它应该触发
ReJoinGroup()
方法

此外,为了确保
属性正常工作,您还需要:

  • 调用
    RemoveFromGroupAsync
    以删除旧的
    映射
  • 调用
    AddToGroupAsync
    添加新的
    映射
通常,您可能希望将这些信息存储在Redis或RDBMS中。出于测试目的,我创建了一个演示,将这些映射存储在内存中供您参考:

公共类MyHub:Hub
{
///存储映射的内存存储区
专用词典_userConn=新词典();
私有只读信号量lim _信号量=新信号量lim(1,1);
公共覆盖异步任务OnConnectedAsync()
{
//通过userId获取真实的组名,
//出于测试目的,我使用userId作为组名,
//在您的场景中,您可以使用聊天室Id
var groupName=Context.UserIdentifier;
等待此消息。重新加入组(groupName);
}
//每当建立连接时,调用此集线器方法来更新存储
公共异步任务重新加入组(字符串groupName)
{
var newConnectionId=Context.ConnectionId;
var userId=Context.UserIdentifier;
等待此消息。_semaphore.WaitAsync();
试一试{
if(_userConn.TryGetValue(userId,out var oldConnectionId))
{
_userConn[userId]=newConnectionId;
//从组中删除旧的connectionId
如果(!string.IsNullOrEmpty(groupName)){
等待组。RemoveFromGroupAsync(oldConnectionId,groupName);
wait Groups.AddToGroupAsync(newConnectionId,groupName);
}
}否则{
_userConn[userId]=newConnectionId;
如果(!string.IsNullOrEmpty(groupName)){
wait Groups.AddToGroupAsync(newConnectionId,groupName);
}
}
}最后{
这个._semaphore.Release();
}
返回新的KeyValuePair(userId,newConnectionId);
}
///您的SendMessageToUser()方法
公共异步任务SendMessageToUser(字符串用户ID,字符串消息)
{
//获取目标用户的connectionId
var userConn=wait this.GetUserConnection(userId);
if(userConn.Equals(默认值(KeyValuePair))){
抛出新异常($“用户ID为{userId}的未知用户连接”);
}
等待Clients.Clients(userConn.Value).SendAsync(Message);
}
///返回一对数据的私人助手
专用异步任务GetUserConnection(字符串用户ID)
{
KeyValuePair kvp=默认值;
字符串newConnectionId=默认值;
等待此消息。_semaphore.WaitAsync();
试一试{
if(this.\u userConn.TryGetValue(userId,out newConnectionId)){
kvp=新的KeyValuePair(userId,newConnectionId);
}
}最后{
这个._semaphore.Release();
}
返回kvp;
}
}

我理解您的逻辑,但它没有存储用户的连接id我不知道为什么,但当我启动另一个连接时,它会再次执行该类并清除以前存储的用户连接是否最好将它们存储在数据库中,而不是缓存中???@HafizMuhammadAtif 1。您是否使用同一用户进行测试?如果是这样,那是因为我使用
userId
作为映射键。我假设如果一个用户有两个连接,旧的连接将被新的连接ID替换。@HafizMuhammadAtif 2。最好使用数据库,正如我上面所说,“通常,您可能希望将这些信息存储在Redis或RDBMS中”。但我不知道您想要使用哪种DB(以及其他具体细节),因此我只能提供一个InMemory实现用于测试目的,它只是一个供您参考的简单代码。无论您选择哪种类型的存储,关键是:将
映射存储到我为两个不同的用户尝试过的位置,这就是它不起作用的原因。我希望将它们存储在数据库中会有所帮助。谢谢你的主意。