SignalR-отправка сообщения конкретному пользователю с помощью (IUserIdProvider) *NEW 2.0.0*

в последней версии Asp.Net SignalR, был добавлен новый способ отправки сообщения конкретному пользователю, используя интерфейс "IUserIdProvider".

public interface IUserIdProvider
{
   string GetUserId(IRequest request);
}

public class MyHub : Hub
{
   public void Send(string userId, string message)
   {
      Clients.User(userId).send(message);
   }
}

мой вопрос: Как узнать, кому я отправляю свое сообщение? Объяснение этого нового метода очень поверхностно. А проект заявления SignalR 2.0.0 с этим багом так и не компилируется. Кто-нибудь реализовал эту функцию?

Подробнее : http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

объятия.

4 ответов


SignalR обеспечивает ConnectionId для каждого соединения. Чтобы найти, какое соединение принадлежит кому (пользователю), нам нужно создать сопоставление между соединением и пользователем. Это зависит от того, как вы идентифицируете пользователя в своем приложении.

в SignalR 2.0 это делается с помощью встроенного IPrincipal.Identity.Name, который является зарегистрированным идентификатором пользователя, установленным во время ASP.NET аутентификация.

однако вам может потребоваться сопоставить соединение с пользователем, используя другой идентификатор вместо использования идентификатора.Имя. Для этой цели этот новый поставщик может использоваться с пользовательской реализацией для сопоставления пользователя с подключением.

пример сопоставления пользователей SignalR с подключениями с помощью IUserIdProvider

предположим, что наше приложение использует userId для идентификации каждого пользователя. Теперь нам нужно отправить сообщение конкретному пользователю. У нас есть userId и message, но SignalR также должен знать отображение между нашим идентификатором пользователя и соединение.

чтобы добиться этого, сначала нам нужно создать новый класс, который реализует IUserIdProvider:

public class CustomUserIdProvider : IUserIdProvider
{
     public string GetUserId(IRequest request)
    {
        // your logic to fetch a user identifier goes here.

        // for example:

        var userId = MyCustomUserClass.FindUserId(request.User.Identity.Name);
        return userId.ToString();
    }
}

второй шаг-сказать SignalR использовать наш CustomUserIdProvider вместо реализации по умолчанию. Это можно сделать при запуске.cs при инициализации конфигурации концентратора:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        var idProvider = new CustomUserIdProvider();

        GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);          

        // Any connection or hub wire up and configuration should go here
        app.MapSignalR();
    }
}

теперь, вы можете отправить сообщение конкретному пользователю, используя его userId как указано в документации, например:

public class MyHub : Hub
{
   public void Send(string userId, string message)
   {
      Clients.User(userId).send(message);
   }
}

надеюсь, что это помогает.


вот начало.. Открыт для предложений/улучшений.

сервер

public class ChatHub : Hub
{
    public void SendChatMessage(string who, string message)
    {
        string name = Context.User.Identity.Name;
        Clients.Group(name).addChatMessage(name, message);
        Clients.Group("2@2.com").addChatMessage(name, message);
    }

    public override Task OnConnected()
    {
        string name = Context.User.Identity.Name;
        Groups.Add(Context.ConnectionId, name);

        return base.OnConnected();
    }
}

JavaScript

(обратите внимание, как addChatMessage и sendChatMessage также являются методами в коде сервера выше)

    $(function () {
    // Declare a proxy to reference the hub.
    var chat = $.connection.chatHub;
    // Create a function that the hub can call to broadcast messages.
    chat.client.addChatMessage = function (who, message) {
        // Html encode display name and message.
        var encodedName = $('<div />').text(who).html();
        var encodedMsg = $('<div />').text(message).html();
        // Add the message to the page.
        $('#chat').append('<li><strong>' + encodedName
            + '</strong>:&nbsp;&nbsp;' + encodedMsg + '</li>');
    };

    // Start the connection.
    $.connection.hub.start().done(function () {
        $('#sendmessage').click(function () {
            // Call the Send method on the hub.
            chat.server.sendChatMessage($('#displayname').val(), $('#message').val());
            // Clear text box and reset focus for next comment.
            $('#message').val('').focus();
        });
    });
});

тестирование enter image description here


посмотреть SignalR Тесты для функции.

тест "SendToUser" автоматически принимает идентификатор пользователя, переданный с помощью обычной библиотеки аутентификации owin.

сценарий у вас есть пользователь, который подключился из нескольких устройств / браузеров, и вы хотите нажать сообщение на все его активные соединения.


вот как использовать SignarR для целевого пользователя (без использования какого-либо поставщика):

 private static ConcurrentDictionary<string, string> clients = new ConcurrentDictionary<string, string>();

 public string Login(string username)
 {
     clients.TryAdd(Context.ConnectionId, username);            
     return username;
 }

// The variable 'contextIdClient' is equal to Context.ConnectionId of the user, 
// once logged in. You have to store that 'id' inside a dictionaty for example.  
Clients.Client(contextIdClient).send("Hello!");