如何将消息发送到 AspNetUsers Table Signal R 中保存的用户 ID
How to send Message to User id Saved in AspNetUsers Table Signal R
我正在尝试发送消息。我试过连接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 Table
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 不会为我们存储 UserId
-ConnectionId
映射。我们需要自己做。例如,当某些用户建立到 Hub 的连接时,它应该触发一个 ReJoinGroup()
方法。
此外,为了确保 Groups
属性 正常工作,您还需要:
- 调用
RemoveFromGroupAsync
删除旧的 <connectionId, groupName>
映射
- 调用
AddToGroupAsync
添加新的 <connectionId, groupName>
映射。
通常,您可能希望将这些信息存储在 Redis 或 RDBMS 中。出于测试目的,我创建了一个将这些映射存储在内存中的演示,供您参考:
public class MyHub:Hub
{
/// a in-memory store that stores the <userId, connectionId> mappings
private Dictionary<string, string> _userConn = new Dictionary<string,string>();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
public override async Task OnConnectedAsync()
{
// get the real group Name by userId,
// for testing purpose, I use the userId as the groupName,
// in your scenario, you could use the ChatRoom Id
var groupName = Context.UserIdentifier;
await this.ReJoinGroup(groupName);
}
// whenever a connection is setup, invoke this Hub method to update the store
public async Task<KeyValuePair<string,string>> ReJoinGroup(string groupName)
{
var newConnectionId = Context.ConnectionId;
var userId = Context.UserIdentifier;
await this._semaphore.WaitAsync();
try{
if(_userConn.TryGetValue(userId, out var oldConnectionId))
{
_userConn[userId]= newConnectionId;
// remove the old connectionId from the Group
if(!string.IsNullOrEmpty(groupName)){
await Groups.RemoveFromGroupAsync(oldConnectionId, groupName);
await Groups.AddToGroupAsync(newConnectionId, groupName);
}
} else {
_userConn[userId]= newConnectionId;
if(!string.IsNullOrEmpty(groupName)){
await Groups.AddToGroupAsync(newConnectionId, groupName);
}
}
} finally{
this._semaphore.Release();
}
return new KeyValuePair<string,string>(userId, newConnectionId);
}
/// your SendMessageToUser() method
public async Task SendMessageToUser(string userId,string Message)
{
// get the connectionId of target user
var userConn = await this.GetUserConnection(userId);
if( userConn.Equals(default(KeyValuePair<string,string>))) {
throw new Exception($"unknown user connection with userId={userId}");
}
await Clients.Clients(userConn.Value).SendAsync(Message);
}
/// a private helper that returns a pair of <UserId,ConnectionId>
private async Task<KeyValuePair<string,string>> GetUserConnection(string userId)
{
KeyValuePair<string,string> kvp = default;
string newConnectionId = default;
await this._semaphore.WaitAsync();
try{
if(this._userConn.TryGetValue(userId, out newConnectionId)){
kvp= new KeyValuePair<string, string>(userId, newConnectionId);
}
} finally{
this._semaphore.Release();
}
return kvp;
}
}
我正在尝试发送消息。我试过连接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 Table
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 不会为我们存储 UserId
-ConnectionId
映射。我们需要自己做。例如,当某些用户建立到 Hub 的连接时,它应该触发一个 ReJoinGroup()
方法。
此外,为了确保 Groups
属性 正常工作,您还需要:
- 调用
RemoveFromGroupAsync
删除旧的<connectionId, groupName>
映射 - 调用
AddToGroupAsync
添加新的<connectionId, groupName>
映射。
通常,您可能希望将这些信息存储在 Redis 或 RDBMS 中。出于测试目的,我创建了一个将这些映射存储在内存中的演示,供您参考:
public class MyHub:Hub
{
/// a in-memory store that stores the <userId, connectionId> mappings
private Dictionary<string, string> _userConn = new Dictionary<string,string>();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
public override async Task OnConnectedAsync()
{
// get the real group Name by userId,
// for testing purpose, I use the userId as the groupName,
// in your scenario, you could use the ChatRoom Id
var groupName = Context.UserIdentifier;
await this.ReJoinGroup(groupName);
}
// whenever a connection is setup, invoke this Hub method to update the store
public async Task<KeyValuePair<string,string>> ReJoinGroup(string groupName)
{
var newConnectionId = Context.ConnectionId;
var userId = Context.UserIdentifier;
await this._semaphore.WaitAsync();
try{
if(_userConn.TryGetValue(userId, out var oldConnectionId))
{
_userConn[userId]= newConnectionId;
// remove the old connectionId from the Group
if(!string.IsNullOrEmpty(groupName)){
await Groups.RemoveFromGroupAsync(oldConnectionId, groupName);
await Groups.AddToGroupAsync(newConnectionId, groupName);
}
} else {
_userConn[userId]= newConnectionId;
if(!string.IsNullOrEmpty(groupName)){
await Groups.AddToGroupAsync(newConnectionId, groupName);
}
}
} finally{
this._semaphore.Release();
}
return new KeyValuePair<string,string>(userId, newConnectionId);
}
/// your SendMessageToUser() method
public async Task SendMessageToUser(string userId,string Message)
{
// get the connectionId of target user
var userConn = await this.GetUserConnection(userId);
if( userConn.Equals(default(KeyValuePair<string,string>))) {
throw new Exception($"unknown user connection with userId={userId}");
}
await Clients.Clients(userConn.Value).SendAsync(Message);
}
/// a private helper that returns a pair of <UserId,ConnectionId>
private async Task<KeyValuePair<string,string>> GetUserConnection(string userId)
{
KeyValuePair<string,string> kvp = default;
string newConnectionId = default;
await this._semaphore.WaitAsync();
try{
if(this._userConn.TryGetValue(userId, out newConnectionId)){
kvp= new KeyValuePair<string, string>(userId, newConnectionId);
}
} finally{
this._semaphore.Release();
}
return kvp;
}
}