如何列出(并遍历)所有当前的ASP.NET会话?
您可以在global.asax事件Session_Start和Session_End中收集有关会话的数据(仅在进程内设置中):
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); } }
您应该考虑使用一些并发集合来降低同步开销.ConcurrentBag或ConcurrentDictionary.或者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
这是如何工作的:
InProc会话数据存储在HttpRuntime的内部缓存中,实现ICollection的ISessionStateItemCollection实现.在这段代码中,首先我获得了HttpRuntime类的CacheInternal静态属性,然后在这个对象的帮助下,我得到了_entries私有成员,它是ICollection类型.然后简单地枚举这个字典,只获取System.Web.SessionState.InProcSessionState类型的对象,最后得到每个用户的SessionStateItemCollection.
摘要:
在本文中,我将向您展示如何获取所有当前用户会话.但是,执行此代码时您会发现一件事是它不会显示当前请求上下文中设置的当前用户Session,因为Session将在所有Page Events之后保存...
没有任何类或方法提供此信息似乎是正确的.我认为,拥有SessionStateStoreProvider功能是一件很好的事情,有一个返回当前活动会话的方法,这样我们就不必像Jan Remunda所提到的那样主动跟踪session_start和session_end中的会话生命.
由于我找不到任何开箱即用的方法来获取所有会话列表,而且我不想跟踪Jan提到的会话生活,我最终得到了这个解决方案,这在我的案例中起作用.
public static IEnumerableGetActiveSessions() { 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; } } } } }
我真的很喜欢ajitdh的回答。不要投票给他。这是对该解决方案的另一种参考:
http://weblogs.asp.net/imranbaloch/reading-all-users-session
这让我接近了,但未能实现我个人的目标,即为我知道的特定会话ID找到会话。因此,出于我的目的,我只是将sessionid作为会话项添加(例如Session Start上的Session [“ SessionId”] = session.SessionId。)然后,我只是寻找一个具有匹配值的会话...通过索引其中一个集合来实际拉出该条目,但这至少可以使它正常工作。
当然,所有这些都用于In-Proc会议,我确实正在考虑远离这些会议。
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; }