Dans la dernière version de Asp.Net SignalR, un nouveau moyen d'envoyer un message à un utilisateur spécifique, en utilisant l'interface "IUserIdProvider", a été ajouté.
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}
Ma question est la suivante: comment savoir à qui j'envoie mon message? L'explication de cette nouvelle méthode est très superficielle. Et le projet de déclaration de SignalR 2.0.0 avec ce bogue et ne compile pas. Quelqu'un at-il implémenté cette fonctionnalité?
Plus d'infos: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider
Câlins.
SignalR fournit ConnectionId pour chaque connexion. Pour trouver quelle connexion appartient à qui (l'utilisateur), nous devons créer un mappage entre la connexion et l'utilisateur. Cela dépend de la manière dont vous identifiez un utilisateur dans votre application.
Dans SignalR 2.0, cela se fait en utilisant le IPrincipal.Identity.Name
, identificateur d'utilisateur connecté défini lors de l'authentification ASP.NET.
Toutefois, vous devrez peut-être mapper la connexion avec l'utilisateur en utilisant un identificateur différent au lieu d'utiliser Identity.Name. À cette fin, ce nouveau fournisseur peut être utilisé avec votre implémentation personnalisée pour mapper l'utilisateur avec la connexion.
Supposons que notre application utilise un userId
pour identifier chaque utilisateur. Nous devons maintenant envoyer un message à un utilisateur spécifique. Nous avons userId
et message
, mais SignalR doit également connaître le mappage entre notre userId et la connexion.
Pour y parvenir, nous devons d’abord créer une nouvelle classe qui implémente 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();
}
}
La deuxième étape consiste à dire à SignalR d’utiliser notre CustomUserIdProvider
au lieu de l’implémentation par défaut. Cela peut être fait dans le fichier Startup.cs lors de l’initialisation de la configuration du concentrateur:
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();
}
}
Maintenant, vous pouvez envoyer un message à un utilisateur spécifique en utilisant son userId
comme mentionné dans la documentation, comme:
public class MyHub : Hub
{
public void Send(string userId, string message)
{
Clients.User(userId).send(message);
}
}
J'espère que cela t'aides.
Voici un début .. Ouvert aux suggestions/améliorations.
Serveur
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
(Notez que addChatMessage
et sendChatMessage
sont également des méthodes dans le code serveur ci-dessus)
$(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();
});
});
});
Essai
Voici comment utiliser SignarR pour cibler un utilisateur spécifique (sans utiliser de fournisseur):
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!");
Regardez Tests SignalR pour la fonctionnalité.
Test "SendToUser" prend automatiquement l'identité de l'utilisateur transmise à l'aide d'une bibliothèque d'authentification owin standard.
Le scénario est que vous avez un utilisateur qui s'est connecté à partir de plusieurs appareils/navigateurs et que vous voulez envoyer un message à toutes ses connexions actives.