I am trying to send a message. I have tried to connection id
public Task SendMessaageToConnectionID(string ConnectionID,string Message)
{
return Clients.Clients(ConnectionID).SendAsync("RecieveMessage", Message);
}
it is successfully done Now I am trying this
public Task SendMessageToUser(string userId,string Message)
{
return Clients.Clients(userId).SendAsync(Message);
}
I am sending the user id of user Saved in AspNetUser 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 won't store the UserId
-ConnectionId
mappings for us. We need to do that by our own. For example, when some user sets up a connection to the Hub, it should trigger a ReJoinGroup()
method.
In addition, in order to make sure the Groups
property works fine, you need also :
RemoveFromGroupAsync
to remove the old <connectionId, groupName>
mappingAddToGroupAsync
to add a new <connectionId, groupName>
mapping.Typically, you might want to store these information in Redis or RDBMS. For testing purpose, I create a demo that stores these mappings in memory for your reference:
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;
}
}