List all active ASP.NET Sessions
Solution 1
You can collect data about sessions in global.asax events Session_Start and Session_End (only in in-proc settings):
private static readonly List<string> _sessions = new List<string>();
private static readonly object padlock = new object();
public static List<string> 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);
}
}
You should consider use some of concurrent collections to lower the synchronization overhead. ConcurrentBag or ConcurrentDictionary. Or ImmutableList
https://msdn.microsoft.com/en-us/library/dd997373(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/dn467185.aspx
Solution 2
It does not seems right that there is not any class or method that provides this information. I think, it is a nice to have feature for SessionStateStoreProvider, to have a method which returns current active session, so that we don't have to actively track session life in session_start and session_end as mention by Jan Remunda.
Since I could not find any out of box method to get all session list, And I did not wanted to track session life as mentioned by Jan, I end up with this solution, which worked in my case.
public static IEnumerable<SessionStateItemCollection> 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;
}
}
}
}
}
Solution 3
http://weblogs.asp.net/imranbaloch/archive/2010/04/05/reading-all-users-session.aspx
How this works :
InProc session data is stored in the HttpRuntime’s internal cache in an implementation of ISessionStateItemCollection that implements ICollection. In this code, first of all i got CacheInternal Static Property of HttpRuntime class and then with the help of this object i got _entries private member which is of type ICollection. Then simply enumerate this dictionary and only take object of type System.Web.SessionState.InProcSessionState and finaly got SessionStateItemCollection for each user.
Summary :
In this article, I show you how you can get all current user Sessions. However one thing you will find when executing this code is that it will not show the current user Session which is set in the current request context because Session will be saved after all the Page Events...
Solution 4
I've been looking around for an equivalent of @ajitdh's answer for later versions of ASP.net - couldn't find anything, so thought I'd update this thread with solution for v4.6.2... Haven't tested with later versions of .net, but it doesn't work with v4.5. I am guessing it will be compatible with v4.6.1 onward.
Cache cache = HttpRuntime.Cache;
MethodInfo method = typeof( System.Web.Caching.Cache ).GetMethod( "GetInternalCache", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy );
object objx = method.Invoke( cache, new object[] { false } );
FieldInfo field = objx.GetType().GetField( "_cacheInternal", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
objx = field.GetValue( objx );
field = objx.GetType().GetField( "_cachesRefs", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
objx = field.GetValue( objx );
IList cacherefs = ( (IList)objx );
foreach( object cacheref in cacherefs )
{
PropertyInfo prop = cacheref.GetType().GetProperty( "Target", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance );
object y = prop.GetValue( cacheref );
field = y.GetType().GetField( "_entries", BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Instance );
Hashtable c2 = (Hashtable)field.GetValue( y );
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 )
{
// Do your stuff with the session!
}
}
}
}
Solution 5
I really like ajitdh's answer. Do upvote him. Here's another reference to that solution:
http://weblogs.asp.net/imranbaloch/reading-all-users-session
This got me close, but it failed to achieve my personal goal of finding the session for a particular session Id that I knew. So, for my purposes, I just added the sessionid as a session item (say Session["SessionId"] = session.SessionId on Session Start.) Then I just looked for a session with a matching value... I would have preferred to actually pull out this entry by indexing into one of the collections, but this did get it working at least.
Of course, this is all for In-Proc sessions, which I am indeed considering moving away from.
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;
}
Alex
Updated on November 10, 2020Comments
-
Alex over 3 years
How can I list (and iterate through) all current ASP.NET sessions?
-
Alex over 14 yearsThat's an iteration across the current session's keys. I want to iterate and display data from all sessions currently active within the server's session state.
-
userx almost 12 yearsThis will only work for InProc sessions as all other session types won't raise the
Session_End()
event. -
Stefan Steiger over 11 years@pilavdzice: If you have SQLServer sessions, then the task is trivial. Just query the session table and serialize the session object(s).
-
Jagz W over 10 yearsfantastic work by imran. I have question, how do I get sessions id value instead of sessions values
-
Aridane Álamo over 9 yearsNot only won't raise Session_End, if you have a webfarm for load balancing the session will only be added on the current server.
-
Ben Gripka over 8 yearsThe method used in this article will only work in a full trust environment. This worked fine in development and failed quickly in production.
-
Sprague over 7 yearslocking at the property is wrong for many reasons. initialise to new list in a static constructor or inline with the field. the locking should go around the add and remove and also any enumerations, or use a synchronised collection
-
Jan Remunda over 7 yearsThanks a lot for the feedback guys. The answer was quite old anyway, so I updated it little bit.
-
Alfred Wallace about 5 yearsIn SQL Server Management Studio, the command to access sessions is
exec sp_who
. dataedo.com/kb/query/sql-server/list-database-sessions -
Jerome Viveiros over 4 yearsThis should be the accepted answer now. The older solution can't work at all in newer versions of .Net.