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);
}
}
Мой вопрос: откуда я знаю, кому я отправляю свое сообщение? Объяснение этого нового метода очень поверхностно. И проект Statement SignalR 2.0.0 с этой ошибкой и не компилируется. Кто-нибудь реализовал эту функцию?
Дополнительная информация: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider
Hugs.
Ответы
Ответ 1
SignalR предоставляет ConnectionId для каждого соединения. Чтобы узнать, какое соединение принадлежит кому (пользователю), нам нужно создать сопоставление между соединением и пользователем. Это зависит от того, как вы идентифицируете пользователя в своем приложении.
В SignalR 2.0 это делается с помощью встроенного IPrincipal.Identity.Name
, который является зарегистрированным идентификатором пользователя, установленным во время аутентификации ASP.NET.
Однако вам может понадобиться сопоставить соединение с пользователем с использованием другого идентификатора вместо использования Identity.Name. Для этого этот новый провайдер может использоваться с вашей пользовательской реализацией для сопоставления пользователя с подключением.
Пример подключения пользователей SignalR к соединениям с помощью IUserIdProvider
Предположим, что наше приложение использует userId
для идентификации каждого пользователя. Теперь нам нужно отправить сообщение конкретному пользователю. У нас есть userId
и message
, но SignalR также должен знать сопоставление между нашим userId и соединением.
Для этого сначала нужно создать новый класс, который реализует 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
вместо стандартной реализации. Это можно сделать в Startup.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);
}
}
Надеюсь, что это поможет.
Ответ 2
Здесь начинается... Открыто для предложений/улучшений.
Сервер
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("[email protected]").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>: ' + 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]()
Ответ 3
Посмотрите Тесты SignalR для этой функции.
Тест "SendToUser" автоматически принимает идентификатор пользователя, используя обычную библиотеку аутентификации owin.
В сценарии у вас есть пользователь, подключенный к нескольким устройствам/браузерам, и вы хотите направить сообщение всем его активным соединениям.