Listar todas las sesiones activas de ASP.NET

¿Cómo puedo listar (e iterar) todas las sesiones actuales de ASP.NET?

Puede recostackr datos sobre sesiones en eventos global.asax Session_Start y Session_End (solo en configuraciones in-proc):

private static readonly List _sessions = new List(); private static readonly object padlock = new object(); public static List Sessions { get { return _sessions; } } protected void Session_Start(object sender, EventArgs e) { lock (padlock) { _sessions.Add(Session.SessionID); } } protected void Session_End(object sender, EventArgs e) { lock (padlock) { _sessions.Remove(Session.SessionID); } } 

Considere utilizar algunas colecciones concurrentes para reducir la sobrecarga de sincronización. ConcurrentBag o ConcurrentDictionary. O ImmutableList

https://msdn.microsoft.com/en-us/library/dd997373(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/dn467185.aspx

http://weblogs.asp.net/imranbaloch/archive/2010/04/05/reading-all-users-session.aspx

Cómo funciona esto:

Los datos de la sesión InProc se almacenan en el caché interno de HttpRuntime en una implementación de ISessionStateItemCollection que implementa ICollection. En este código, antes que nada obtuve CacheInternal Static Property de la clase HttpRuntime y luego con la ayuda de este objeto obtuve _entries private member que es del tipo ICollection. Luego simplemente enumere este diccionario y solo tome el objeto de tipo System.Web.SessionState.InProcSessionState y finalmente obtenga SessionStateItemCollection para cada usuario.

Resumen :

En este artículo, te muestro cómo puedes obtener todas las sesiones de usuario actuales. Sin embargo, una cosa que encontrará al ejecutar este código es que no mostrará la sesión del usuario actual que se establece en el contexto de solicitud actual porque la sesión se guardará después de todos los eventos de página …

No parece correcto que no haya ninguna clase o método que proporcione esta información. Creo que es una característica interesante tener SessionStateStoreProvider, tener un método que devuelva la sesión activa actual, para que no tengamos que seguir activamente la vida de la sesión en session_start y session_end como menciona Jan Remunda.

Como no pude encontrar ningún método para obtener toda la lista de sesiones, y no quería seguir la vida de la sesión mencionada por Jan, termino con esta solución, que funcionó en mi caso.

 public static IEnumerable GetActiveSessions() { 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) { yield return sess; } } } } } 

Realmente me gusta la respuesta de Ajitdh. Votarlo arriba. Aquí hay otra referencia a esa solución:

http://weblogs.asp.net/imranbaloch/reading-all-users-session

Esto me acercó, pero no logró mi objective personal de encontrar la sesión para una sesión en particular Id que yo conocía. Entonces, para mis propósitos, acabo de agregar el sessionid como un elemento de la sesión (digamos Session [“SessionId”] = session.SessionId en Session Start.) Luego busqué una sesión con un valor coincidente … Hubiera preferido para realmente sacar esta entrada al indexar en una de las colecciones, pero esto hizo que funcionara al menos.

Por supuesto, esto es todo por sesiones In-Proc, de las cuales estoy considerando mudarme.

 private static SessionStateItemCollection GetSession(string sessionId) { 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 o0 = entry.Value.GetType().GetProperty("Value", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(entry.Key, null); 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["SessionId"] != null && ((string)sess["SessionId"]) == sessionId) { return sess; } } } } } return null; } 

Aquí hay un ejemplo de WebForms / Identity que obtiene una lista de los usuarios que han iniciado sesión activos en los últimos 30 minutos.

La siguiente respuesta funciona para un único servidor web, y la memoria caché se perderá si la aplicación se reinicia. Si desea conservar los datos y compartirlos entre los servidores en una granja de servidores web, esta respuesta podría ser de su interés.

En Global.asa.cs:

 public static ActiveUsersCache ActiveUsersCache { get; } = new ActiveUsersCache(); 

y

 protected void Application_PreRequestHandlerExecute(object sender, EventArgs e) { if (User != null && User.Identity.IsAuthenticated) { // Only update when the request is for an .aspx page if (Context.Handler is System.Web.UI.Page) { ActiveUsersCache.AddOrUpdate(User.Identity.Name); } } } 

El agregar estas dos clases:

 public class ActiveUsersCache { private readonly object padlock = new object(); private readonly Dictionary cache = new Dictionary(); private DateTime lastCleanedAt; public int ActivePeriodInMinutes { get; } = 30; private const int MinutesBetweenCacheClean = 30; public List GetActiveUsers() { CleanCache(); var result = new List(); lock (padlock) { result.AddRange(cache.Select(activeUser => new ActiveUser {Name = activeUser.Key, LastActive = activeUser.Value})); } return result; } private void CleanCache() { lastCleanedAt = DateTime.Now; var cutoffTime = DateTime.Now - TimeSpan.FromMinutes(ActivePeriodInMinutes); lock (padlock) { var expiredNames = cache.Where(au => au.Value < cutoffTime).Select(au => au.Key).ToList(); foreach (var name in expiredNames) { cache.Remove(name); } } } public void AddOrUpdate(string userName) { lock (padlock) { cache[userName] = DateTime.Now; } if (IsTimeForCacheCleaup()) { CleanCache(); } } private bool IsTimeForCacheCleaup() { return lastCleanedAt < DateTime.Now - TimeSpan.FromMinutes(MinutesBetweenCacheClean); } } public class ActiveUser { public string Name { get; set; } public DateTime LastActive { get; set; } public string LastActiveDescription { get { var timeSpan = DateTime.Now - LastActive; if (timeSpan.Minutes == 0 && timeSpan.Seconds == 0) return "Just now"; if (timeSpan.Minutes == 0) return timeSpan.Seconds + "s ago"; return $"{timeSpan.Minutes}m {timeSpan.Seconds}s ago"; } } } 

Finalmente, en la página donde desea mostrar los usuarios activos, muestre los resultados:

 UserRepeater.DataSource = Global .ActiveUsersCache.GetActiveUsers().OrderByDescending(u => u.LastActive); UserRepeater.DataBind(); 

Hasta donde yo sé, con las sesiones estándar en memoria no puedes. Esto es algo con lo que estaba lidiando la semana pasada y llegué a la determinación de que no es posible a menos que esté usando un servidor de estado de sesión. Parece bastante extraño desde el punto de vista del diseño si me preguntas. : /

Pruebe el siguiente código

  for (int i = 0; i < Session.Keys.Count - 1; i++) { Label1.Text += Session.Keys.Get(i) + " - " + Session[i].ToString()+"
"; }