123 votes

SignalR - Envoi d'un message à un utilisateur spécifique en utilisant (IUserIdProvider) *NOUVEAU 2.0.0*

Dans la dernière version d'Asp.Net SignalR, une nouvelle façon d'envoyer un message à un utilisateur spécifique a été ajoutée, en utilisant l'interface "IUserIdProvider".

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 : 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 présente ce bug et ne compile pas. Est-ce que quelqu'un a implémenté cette fonctionnalité ?

Plus d'informations : http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

Bisous.

177voto

Sumant Points 1331

SignalR fournit un ConnectionId pour chaque connexion. Pour trouver à qui appartient chaque connexion (l'utilisateur), nous devons créer une correspondance entre la connexion et l'utilisateur. Cela dépend de la façon dont vous identifiez un utilisateur dans votre application.

Dans SignalR 2.0, cela se fait en utilisant IPrincipal.Identity.Name intégré, qui est l'identifiant de l'utilisateur connecté tel que défini lors de l'authentification ASP.NET.

Cependant, vous pouvez avoir besoin de mapper la connexion avec l'utilisateur en utilisant un identifiant 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.

Exemple de mappage des utilisateurs SignalR aux connexions en utilisant IUserIdProvider

Supposons que notre application utilise un userId pour identifier chaque utilisateur. Maintenant, nous devons envoyer un message à un utilisateur spécifique. Nous avons userId et message, mais SignalR doit également connaître la correspondance entre notre userId et la connexion.

Pour ce faire, nous devons d'abord créer une nouvelle classe qui implémente IUserIdProvider:

public class CustomUserIdProvider : IUserIdProvider
{
     public string GetUserId(IRequest request)
    {
        // votre logique pour récupérer un identifiant d'utilisateur va ici.

        // par exemple :

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

La deuxième étape consiste à indiquer à 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 hub :

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

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

        // Toute connexion ou configuration de hub doit être faite ici
        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);
   }
}

50voto

The Muffin Man Points 5858

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("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

(Remarquez comment addChatMessage et sendChatMessage sont aussi des méthodes dans le code serveur ci-dessus)

    $(function () {
    // Déclarer un proxy pour référencer le hub.
    var chat = $.connection.chatHub;
    // Créer une fonction que le hub peut appeler pour diffuser des messages.
    chat.client.addChatMessage = function (who, message) {
        // Encoder en HTML le nom d'affichage et le message.
        var encodedName = $('

Test saisir la description de l'image ici

8voto

Gary89 Points 42

C'est ainsi que vous utilisez SignarR pour cibler un utilisateur spécifique (sans utiliser de fournisseur) :

 private static ConcurrentDictionary clients = new ConcurrentDictionary();

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

// La variable 'contextIdClient' est égale à Context.ConnectionId de l'utilisateur, une fois connecté. Vous devez stocker cet 'id' dans un dictionnaire par exemple.  
Clients.Client(contextIdClient).send("Bonjour!");

6voto

Qudus Points 22

Pour toute personne essayant de le faire en asp.net core. Vous pouvez utiliser des claims.

public class CustomEmailProvider : IUserIdProvider
{
    public virtual string GetUserId(HubConnectionContext connection)
    {
        return connection.User?.FindFirst(ClaimTypes.Email)?.Value;
    }
}

N'importe quel identifiant peut être utilisé, mais il doit être unique. Si vous utilisez un identifiant de nom par exemple, cela signifie que s'il y a plusieurs utilisateurs avec le même nom que le destinataire, le message leur serait également livré. J'ai choisi l'email car il est unique pour chaque utilisateur.

Ensuite, enregistrez le service dans la classe de démarrage.

services.AddSingleton();

Ensuite. Ajoutez les claims lors de l'enregistrement de l'utilisateur.

var result = await _userManager.CreateAsync(user, Model.Password);
if (result.Succeeded)
{
    await _userManager.AddClaimAsync(user, new Claim(ClaimTypes.Email, Model.Email));
}

Pour envoyer un message à un utilisateur spécifique.

public class ChatHub : Hub
{
    public async Task SendMessage(string receiver, string message)
    {
        await Clients.User(receiver).SendAsync("ReceiveMessage", message);
    }
}

Remarque : L'expéditeur du message ne sera pas notifié que le message a été envoyé. Si vous souhaitez une notification du côté de l'expéditeur. Changez la méthode SendMessage en ceci.

public async Task SendMessage(string sender, string receiver, string message)
{
    await Clients.Users(sender, receiver).SendAsync("ReceiveMessage", message);
}

Ces étapes ne sont nécessaires que si vous devez modifier l'identifiant par défaut. Sinon, passez à la dernière étape où vous pouvez simplement envoyer des messages en passant des userIds ou des connectionIds à SendMessage. Pour plus d'informations

2voto

Gustavo Armenta Points 1291

Regardez les tests SignalR pour la fonctionnalité.

Le test "SendToUser" prend automatiquement l'identité de l'utilisateur passée en utilisant une bibliothèque d'authentification owin régulière.

Le scénario est que vous avez un utilisateur qui s'est connecté à partir de plusieurs appareils/navigateurs et vous voulez envoyer un message à toutes ses connexions actives.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X