Как отправить сообщение идентификатору пользователя, сохраненному в таблице AspNetUsers Signal R - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь отправить сообщение. Я пытался подключиться с идентификатором

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 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?

1 Ответ

1 голос
/ 22 января 2020

SignalR не будет хранить для нас отображения UserId - ConnectionId. Нам нужно сделать это самостоятельно. Например, когда какой-либо пользователь устанавливает соединение с концентратором, он должен запустить метод 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;
    }

}
...