在我的登录网页上(即用户点击的第一页)我有这种形式的代码:
public class MyPage : System.Web.UI.Page {
private MyClass _obj = new MyClass();
...
MyClass
有构造函数:
public MyClass() {
var sess = HttpContext.Current.Session; // no problem here
sess["MyValue"] = 123; // throws null ref exception coz sess is null
}
正如我所评论的那样,对sess["MyValue"]
的调用会引发空引用异常,因为HttpContext尚未创建会话对象。
那么何时开始访问Session对象是安全的?我不想放弃_obj
的内联声明/初始化;这对我来说非常方便!我有哪些替代方案?
答案 0 :(得分:14)
您应该能够在Page的OnInit
事件中或之后访问会话,或PreInit
如果您感到困扰,则可以访问会话。在那之前,你就死了。
答案 1 :(得分:4)
会话在Http Module管道的 aquireRequestState 事件中创建。我试图在下面详细解释这一切。
我们在Http Module管道中有以下事件:
(页面前生命周期)
1. BeginRequest
2. AuthenticateRequest
3.授权请求
4. ResolveRequestCache
5. AcquireRequestState
6. PreRequestHandlerExecute
帖子后生命周期
7. PostRequestHandlerExecute
8. ReleaseRequestState
9. UpdateRequestCache
10. EndRequest
现在,正如我们所知,页面生命周期中的第一个事件是 PreInit 。 您正尝试在 PreInit 事件之前创建对象 _obj 。在请求生命周期中,这个对象的创建过程和构造函数的执行是在ResolveRequestCache期间完成的,即;在 AcquireRequestState 事件之前(因为这是在类中直接创建的,而不是任何方法)。正如预期的那样,由于 AcquireRequestState 尚未执行,因此构造函数中的会话仍然不可用。
页面生命周期中的PreInit 方法在 AcquireRequestState 之后调用,因此会话在那里可用。
<强>结论:强> 最早的会话操作可以在Http Modules中的 AcquireRequestState 之后的任何时间完成(如果您以编程方式拦截请求)或在 PreInit 方法中/之后。
答案 2 :(得分:2)
如果用户位于站点的第一页,则会话中没有对象。在分配之前,你一定要检查它。
if (Session["MyValue"] == null)
Session.Add("MyValue", "");
Session["MyValue"] = "123";
您还可以将Global.asax文件添加到项目中。这是您可以处理Session_Start
事件的地方。
答案 3 :(得分:1)
您可以查看http管道。 Rich Starhl有一个nice article.。在aquireRequestState事件期间创建/检索会话对象。如果您有HTTP模块在此事件之前拦截请求,则您的会话可能尚未初始化