【问题标题】:.NET - Session object is null in static methods.NET - 会话对象在静态方法中为空
【发布时间】:2012-05-29 21:52:47
【问题描述】:

我一直在尝试为我的一些类实现一个静态“Current”属性,使其表现得像 HttpContext.Current 属性。那些仅依赖于上下文或请求标头的行为正常。但是,那些依赖于当前 Session 对象的失败。在这些情况下,Session 对象似乎为空:

// THIS WORKS
private static HttpContext Context { get { return HttpContext.Current; } }

// THIS APPEARS TO YIELD NULL
private static HttpSessionState Session { get { return HttpContext.Current.Session; } }

public static EducationalUnit Current
{
    get
    {
        if (Context.Items["EducationalUnit.Current"] == null)
        {
            SetCurrent();
        }
        return (EducationalUnit)Context.Items["EducationalUnit.Current"];
    }

    set
    {
        Context.Items["EducationalUnit.Current"] = value;
    }
} // Current


// I've tried a few things here, to scope out the status of the Session:
private static void SetCurrent()
{
    // shows "null"
    throw new Exception(Session);

    // shows "null"
    throw new Exception(Session.SessionID);

    // also shows "null"
    throw new Exception(HttpContext.Current.Session);

    // shows "Object reference not set to an instance of an object."
    throw new Exception(HttpContext.Current.Session.SessionID);

    // this, however, properly echos my cookie keys!
    JavaScriptSerializer js = new JavaScriptSerializer();
    throw new Exception(js.Serialize(Context.Request.Cookies.Keys.ToString()));

} // SetCurrent()

在我的一生中,我无法从 SetCurrent() 方法中获取会话。

有什么想法吗?

谢谢!

【问题讨论】:

    标签: .net session static


    【解决方案1】:

    非常简单的答案:在 Session 初始化之前,某个地方(还不确定是什么)正在访问 EducationalUnit.Current。在添加条件以测试 Session 是否为 null 并且默默地什么都不做时,错误消失了,一切正常。

    而且无论什么影响 EducationalUnit.Current 可能都不需要,因为它似乎不会影响任何东西......

    感谢您的反馈!

    附录:当 EducationalUnit.Current 被 Page 属性间接命中时,就会出现问题:

    public partial class client_configuration : System.Web.UI.Page
    {
        //
        // The problem occurs here:
        //
    
        private Client c = Client.Current;
    
        //
        // Client objects refer to EducationalUnit.Current, which attempts
        // to use the Session, which doesn't exist at Page instantiation time.
        // 
        // (The assignment can safely be moved to the Page_Load event.)
        //
    
    
        protected void Page_Load(object sender, EventArgs e)
        {
            // etc.
        }
    }
    

    这是最终的(有效的)EducationalUnit 代码:

    private static HttpContext Context { get { return HttpContext.Current; } }
    private static HttpSessionState Session { get { return HttpContext.Current.Session; } }
    
    
    public static EducationalUnit Current
    {
        get
        {
            if (Context.Items["EducationalUnit.Current"] == null)
            {
                SetCurrent();
            }
            return (EducationalUnit)Context.Items["EducationalUnit.Current"];
        }
    
        set
        {
            Context.Items["EducationalUnit.Current"] = value;
        }
    } // Current
    
    
    private static void SetCurrent()
    {
        if (Session == null)
        {
            throw new Exception("Session is not initialized!");
        }
        else
        {
            try
            {
                Guid EUID = new Guid(Session["classroomID"].ToString());
                Current = new EducationalUnit();
                Current.GetDetails(EUID);
            }
            catch
            {
                Current = new EducationalUnit();
            }
        }
    } // SetCurrent()
    

    【讨论】:

    • 明天当我回到办公室时,我可以用实际的工作代码更新它。这可能是你所期望的。但是,无论如何我都会发布它以向每个人验证它是否按预期工作!事实上,宇宙中有秩序......
    【解决方案2】:

    您的问题是,虽然 HttpContext.Current 是静态属性,但它返回的对象的属性不是。当您尝试private static HttpSessionState Session { get { return HttpContext.Current.Session; } } 时,该值会在第一个引用上填充,此后永远不会更新。因此,您将获得 HttpContext.Current.Session 持有的第一个值。它保持空值,即没有引用,因此它没有对对象的引用,并且您对该属性的调用将始终返回空值。我只能告诉你不要那样做。

    此外,根据您的类在链中被调用的位置,它可能无法访问任何有用的值。通常对于静态类,让方法将 HttpContext 作为参数更安全。

    好的...让我们看看 Session 的实际工作原理,在幕后你拥有的是这样的:

        SessionStateModule  _sessionStateModule;    // if non-null, it means we have a delayed session state item
    
        public HttpSessionState Session { 
            get {  
                if (_sessionStateModule != null) { 
                    lock (this) {  
                        if (_sessionStateModule != null) {  
                            // If it's not null, it means we have a delayed session state item 
                            _sessionStateModule.InitStateStoreItem(true);  
                            _sessionStateModule = null; 
                        } 
                    } 
                }  
    
                return (HttpSessionState)Items[SessionStateUtility.SESSION_KEY];  
            }  
        }
    
        public IDictionary Items {  
            get {  
                if (_items == null) 
                    _items = new Hashtable();  
    
                return _items; 
            } 
        }  
    

    请注意,它在其链中的任何地方都不是静态的。 Web 应用程序遵循特定的生命周期,并且会话可能并不总是存在,具体取决于您在生命周期中的哪个位置......(超时。待续。)

    【讨论】:

    • 我不确定我是否遵循。为什么我可以从 HttpContext.Current 访问 Request 和 Response 对象?
    • 因为 HttpContext.Current 是对已存在对象的静态引用。当对象更新时,仍然通过引用获取对它的访问,因此可以通过该引用正常访问它的属性,然后为您提供更新的引用/值。
    • 我知道它是对现有对象的静态引用(更可能是 getter)。这并不能解释为什么 Session 属性不存在。而且它没有解释为什么对底层对象的更新会破坏引用。我也很困惑为什么这似乎对其他人有用,如果你确定它不应该:stackoverflow.com/questions/1913821/…stackoverflow.com/questions/2804256/…
    • 正在做一个详细的解释,但时间不够。
    • 我不确定这是否是您要说的,但简单的答案,虽然基于上面的代码推测,是会话尚未初始化第一次 EducationalUnit.Current正在被访问。请参阅下面的答案。
    【解决方案3】:

    试试HttpContext.Current.Session

    【讨论】:

    • 如果这不起作用,请将会话状态(或您需要的)作为参数传递给方法
    • 试过了。尝试了 SetCurrent 方法中的每一行 throw new Exception ...。前三个都产生 null。
    • 尽量避免这种情况,如果可以的话,因为它违背了提供易于访问 {ClassName}.Current 对象的目的。
    • 好吧,你使用了 HttpContext.*Context*.Session --- HttpContext.*Current*.Session 行为不同。
    • 抱歉——这是在编辑帖子时出现的拼写错误。我会在上面更正它。
    【解决方案4】:

    这可能与所提出的问题无关,但可能对某人有所帮助。

    我有一个Generic Handler (.ashx),它正在发送一些用户控件的输出,这些控件又具有对象数据源,这些对象数据源是静态方法(在静态类中)。 这些静态方法利用了会话对象。通过。 HttpContext.Current.Session.

    但是,Session 对象为空。

    进一步查找后,我发现当您使用通用处理程序时, 如果要访问会话对象,则必须在处理程序类上实现标记接口IReadOnlySessionState。 作为

       public class AjaxHandler : IHttpHandler, IReadOnlySessionState
            {
             public void ProcessRequest(HttpContext context)
                {
                /* now both context.Session as well as 
        HttpContext.Current.Session will give you session values.
        */
                string str = AjaxHelpers.CustomerInfo();
    
                }
    
            }
    
    public static class AjaxHelpers
        {
            public static string CustomerInfo()
            {
               //simplified for brevity.
    return HttpContext.Current.Session["test"];
    
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2011-07-31
      • 2023-01-27
      • 1970-01-01
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      相关资源
      最近更新 更多