asp.net mvc SignalR-Enviar un mensaje a un usuario específico usando(IUserIdProvider)*NUEVO 2.0.0*




signalr websocket (4)

En la última versión de Asp.Net SignalR, se agregó una nueva forma de enviar un mensaje a un usuario específico, utilizando la interfaz "IUserIdProvider".

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

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

Mi pregunta es: ¿cómo sé a quién estoy enviando mi mensaje? La explicación de este nuevo método es muy superficial. Y el borrador del Statement of SignalR 2.0.0 con este error y no compila. ¿Alguien ha implementado esta característica?

Más información: http://www.asp.net/signalr/overview/signalr-20/hubs-api/mapping-users-to-connections#IUserIdProvider

Abrazos.


SignalR proporciona ConnectionId para cada conexión. Para encontrar qué conexión pertenece a quién (el usuario), debemos crear una asignación entre la conexión y el usuario. Esto depende de cómo identificas a un usuario en tu aplicación.

En SignalR 2.0, esto se hace utilizando el IPrincipal.Identity.Name incorporado, que es el identificador de usuario registrado como establecido durante la autenticación ASP.NET.

Sin embargo, puede necesitar asignar la conexión con el usuario usando un identificador diferente en lugar de usar Identity.Name. Para este propósito, este nuevo proveedor se puede usar con su implementación personalizada para mapear al usuario con la conexión.

Ejemplo de asignación de usuarios de SignalR a las conexiones utilizando IUserIdProvider

Supongamos que nuestra aplicación usa un userId de usuario para identificar a cada usuario. Ahora, necesitamos enviar un mensaje a un usuario específico. Tenemos userId y message , pero SignalR también debe conocer la asignación entre nuestro ID de usuario y la conexión.

Para lograr esto, primero tenemos que crear una nueva clase que implemente 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();
    }
}

El segundo paso es decirle a SignalR que use nuestro CustomUserIdProvider lugar de la implementación predeterminada. Esto se puede hacer en Startup.cs al inicializar la configuración del hub:

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();
    }
}

Ahora puede enviar un mensaje a un usuario específico usando su userId usuario como se menciona en la documentación, como:

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

Espero que esto ayude.


Aquí hay un comienzo ... Abierto a sugerencias / mejoras.

Servidor

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

(Observe cómo addChatMessage y sendChatMessage también son métodos en el código del servidor anterior)

    $(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();
        });
    });
});

Pruebas


Así es como usar SignarR para apuntar a un usuario específico (sin usar ningún proveedor):

 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!");

Mire las Pruebas SignalR para la característica.

La prueba "SendToUser" lleva automáticamente a la identidad del usuario pasada utilizando una biblioteca de autenticación owin regular.

El escenario es que tiene un usuario que se ha conectado desde múltiples dispositivos / navegadores y desea enviar un mensaje a todas sus conexiones activas.