2012-01-13 28 views
14

sé lo que el usuario ha iniciado la sesión con la siguiente línea de código:Obtener una lista de todas las sesiones activas en ASP.NET

Session["loggedInUserId"] = userId; 

La pregunta que tengo es ¿cómo sé lo que los usuarios se registran en la que otros usuarios puedan ver qué usuarios están actualmente conectados.

En otras palabras, ¿puedo obtener todas las sesiones "loggedInUserId" que están activas?

+0

posible duplicado de [Lista de todos activos ASP.NET Sesiones] (http://stackoverflow.com/questions/1470334/list-all-active-asp-net-sessions) –

Respuesta

19

No probé la solución rangitatanz, pero utilicé otro método y funcionó muy bien para mí.

private List<String> getOnlineUsers() 
    { 
     List<String> activeSessions = new List<String>(); 
     object obj = typeof(HttpRuntime).GetProperty("CacheInternal", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null); 
     object[] obj2 = (object[])obj.GetType().GetField("_caches", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj); 
     for (int i = 0; i < obj2.Length; i++) 
     { 
      Hashtable c2 = (Hashtable)obj2[i].GetType().GetField("_entries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(obj2[i]); 
      foreach (DictionaryEntry entry in c2) 
      { 
       object o1 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Value, null); 
       if (o1.GetType().ToString() == "System.Web.SessionState.InProcSessionState") 
       { 
        SessionStateItemCollection sess = (SessionStateItemCollection)o1.GetType().GetField("_sessionItems", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(o1); 
        if (sess != null) 
        { 
         if (sess["loggedInUserId"] != null) 
         { 
          activeSessions.Add(sess["loggedInUserId"].ToString()); 
         } 
        } 
       } 
      } 
     } 
     return activeSessions; 
    } 
+1

¡Muy bueno! Nota: esto debe optimizarse para que la reflexión se guarde en caché. También, por supuesto, ambas soluciones fallarán si el sitio se ejecuta en múltiples nodos web. –

+4

Buena publicación. Estoy obteniendo un error en la línea 'object [] obj2 = (object []) obj.GetType(). GetField (" _ caches ", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue (obj);' en iis6 (servidor Windows 2003). Funciona bien en Windows XP y Windows 7. – TechDo

+0

¿Y si necesito el SessionID para cada sesión activa? – Bergkamp

4

hay una solución que figuran en esta página List all active ASP.NET Sessions

private static List<string> _sessionInfo; 
private static readonly object padlock = new object(); 

public static List<string> Sessions 
{ 
     get 
     { 
      lock (padlock) 
      { 
       if (_sessionInfo == null) 
       { 
        _sessionInfo = new List<string>(); 
       } 
       return _sessionInfo; 
      } 
     } 
    } 

    protected void Session_Start(object sender, EventArgs e) 
    { 
     Sessions.Add(Session.SessionID); 
    } 
    protected void Session_End(object sender, EventArgs e) 
    { 
     Sessions.Remove(Session.SessionID); 
    } 

Básicamente se acaba de seguimiento de las sesiones en una lista que se puede utilizar para averiguar información sobre. Realmente puede almacenar algo en lo que realmente desea: nombres de usuario o lo que sea.

No creo que haya nada en la capa ASP .NET que ya lo haga.

+6

Sólo un pequeño recordatorio: IIRC el evento Session_End solo se genera cuando se usa el estado de la sesión InProcess. Al usar StateServer o SQL Server para el estado de la sesión, ese no es el caso, lo que significa que los objetos nunca se eliminarán de su colección _sessionInfo. Por lo tanto, tendría que implementar algún mecanismo de "tiempo de espera" que elimine las sesiones expiradas. – M4N

+2

Según tengo entendido, 'List.Add/Remove' no es seguro para subprocesos. Entonces, ¿no necesita 'bloquear (candado)' en estas operaciones? –

+0

Sí, eso suena correcto. También podría usar uno de estos nuevos ConcurrentCollections, supongo. –

Cuestiones relacionadas