列出所有活动的ASP.NET会话

Ale*_*lex 44 asp.net session session-state

如何列出(并遍历)所有当前的ASP.NET会话?

Jan*_*nda 34

您可以在global.asax事件Session_Start和Session_End中收集有关会话的数据(仅在进程内设置中):

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);
      }
  }
Run Code Online (Sandbox Code Playgroud)

您应该考虑使用一些并发集合来降低同步开销.ConcurrentBag或ConcurrentDictionary.或者ImmutableList

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

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

  • 这只适用于InProc会话,因为所有其他会话类型都不会引发`Session_End()`事件. (10认同)
  • 不仅不会引发Session_End,如果你有一个用于负载均衡的webfarm,那么会话只会添加到当前服务器上. (6认同)
  • 由于许多原因,锁定该物业是错误的.在静态构造函数中初始化为新列表或与字段内联.锁定应该围绕添加和删除以及任何枚举,或使用同步集合 (2认同)
  • 非常感谢反馈人员.无论如何,答案已经很老了,所以我稍微更新了一下. (2认同)
  • 好人!顺便说一句,我看到你的代码在代码项目上被复制了.:d (2认同)

小智 19

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之后保存...

  • 伊姆兰的出色工作.我有疑问,如何获取会话ID值而不是会话值 (2认同)
  • 本文中使用的方法仅适用于完全信任环境.这在开发中运行良好,并且在生产中很快失败. (2认同)

aji*_*tdh 18

没有任何类或方法提供此信息似乎是正确的.我认为,拥有SessionStateStoreProvider功能是一件很好的事情,有一个返回当前活动会话的方法,这样我们就不必像Jan Remunda所提到的那样主动跟踪session_start和session_end中的会话生命.

由于我找不到任何开箱即用的方法来获取所有会话列表,而且我不想跟踪Jan提到的会话生活,我最终得到了这个解决方案,这在我的案例中起作用.

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;
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @pilavdzice:如果你有SQLServer会话,那么任务很简单.只需查询会话表并序列化会话对象即可. (10认同)

Gre*_*reg 5

我真的很喜欢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;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

我一直在寻找与@ajitdh 对更高版本的 ASP.net 的回答相当的答案 - 找不到任何东西,所以我想我会用 v4.6.2 的解决方案更新这个线程......以后还没有测试.net 版本,但它不适用于 v4.5。我猜它会与 v4.6.1 兼容。

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!
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是现在公认的答案。旧的解决方案在新版本的.Net 中根本无法工作。 (3认同)