Saltar al contenido

¿Cómo obtener el ID de conexión del cliente signalR en el lado del servidor?

Solución:

Cuando un cliente invoca una función en el lado del servidor, puede recuperar su ID de conexión a través de Context.ConnectionId. Ahora, si desea acceder a esa identificación de conexión a través de un mecanismo fuera de un concentrador, puede:

  1. Simplemente haga que el Hub invoque su método externo pasando el ID de conexión.
  2. Administre una lista de clientes conectados, también conocidos como public static ConcurrentDictionary<string, MyUserType>... agregando al diccionario en OnConnected y quitando de ella en OnDisconnected. Una vez que tenga su lista de usuarios, puede consultarla a través de su mecanismo externo.

Ej 1:

public class MyHub : Hub
{
    public void AHubMethod(string message)
    {
        MyExternalSingleton.InvokeAMethod(Context.ConnectionId); // Send the current clients connection id to your external service
    }
}

Ej 2:

public class MyHub : Hub
{
    public static ConcurrentDictionary<string, MyUserType> MyUsers = new ConcurrentDictionary<string, MyUserType>();

    public override Task OnConnected()
    {
        MyUsers.TryAdd(Context.ConnectionId, new MyUserType() { ConnectionId = Context.ConnectionId });
        return base.OnConnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        MyUserType garbage;

        MyUsers.TryRemove(Context.ConnectionId, out garbage);

        return base.OnDisconnected(stopCalled);
    }

    public void PushData(){
        //Values is copy-on-read but Clients.Clients expects IList, hence ToList()
        Clients.Clients(MyUsers.Keys.ToList()).ClientBoundEvent(data);
    }
}

public class MyUserType
{
    public string ConnectionId { get; set; }
    // Can have whatever you want here
}

// Your external procedure then has access to all users via MyHub.MyUsers

¡Espero que esto ayude!

La respuesta de Taylor funciona, sin embargo, no tiene en cuenta una situación en la que un usuario tiene varias pestañas del navegador web abiertas y, por lo tanto, tiene varias ID de conexión diferentes.

Para solucionarlo, creé un Diccionario concurrente donde la clave del diccionario es un nombre de usuario y el valor de cada clave es una Lista de conexiones actuales para ese usuario dado.

public static ConcurrentDictionary<string, List<string>> ConnectedUsers = new ConcurrentDictionary<string, List<string>>();

On Connected: agregando una conexión al diccionario de caché global:

public override Task OnConnected()
{
    Trace.TraceInformation("MapHub started. ID: {0}", Context.ConnectionId);
    
    var userName = "testUserName1"; // or get it from Context.User.Identity.Name;

    // Try to get a List of existing user connections from the cache
    List<string> existingUserConnectionIds;
    ConnectedUsers.TryGetValue(userName, out existingUserConnectionIds);

    // happens on the very first connection from the user
    if(existingUserConnectionIds == null)
    {
        existingUserConnectionIds = new List<string>();
    }

    // First add to a List of existing user connections (i.e. multiple web browser tabs)
    existingUserConnectionIds.Add(Context.ConnectionId);

    
    // Add to the global dictionary of connected users
    ConnectedUsers.TryAdd(userName, existingUserConnectionIds);

    return base.OnConnected();
}

Al desconectar (cerrar la pestaña): eliminar una conexión del diccionario de caché global:

public override Task OnDisconnected(bool stopCalled)
{
    var userName = Context.User.Identity.Name;

    List<string> existingUserConnectionIds;
    ConnectedUsers.TryGetValue(userName, out existingUserConnectionIds);

    // remove the connection id from the List 
    existingUserConnectionIds.Remove(Context.ConnectionId);

    // If there are no connection ids in the List, delete the user from the global cache (ConnectedUsers).
    if(existingUserConnectionIds.Count == 0)
    {
        // if there are no connections for the user,
        // just delete the userName key from the ConnectedUsers concurent dictionary
        List<string> garbage; // to be collected by the Garbage Collector
        ConnectedUsers.TryRemove(userName, out garbage);
    }

    return base.OnDisconnected(stopCalled);
}

Ruego diferir sobre la reconexión. El cliente permanece en la lista pero el ID de conexión cambiará. Hago una actualización de la lista estática en las reconexiones para resolver esto.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *