“HttpContext.Current.Session”與 Global.asax “this.Session”
最近,在為工作中的 ASP.NET 項目編寫一些程式碼時。我們需要一個跟踪工具來獲取使用者活動的基本指標(頁麵點擊計數等),我們將跟踪它們,然後通過in
Session將數據保存到 DB 。Session_EndGlobal.asax我開始破解,初始程式碼執行良好,在每個頁面載入時更新數據庫。我想在每個請求上刪除這個數據庫命中,只是依靠
Session_End儲存所有數據。所有跟踪程式碼都封裝在
Tracker類中,包括本質上包裝會話變數的屬性。問題 是當我
Tracker.Log()在Session_End方法中執行時HttpContext.Current.Session,Tracker 程式碼中的NullReferenceException. 現在,這是有道理的,因為HttpContext總是與目前請求相關,當然在 中Session_End,沒有請求。我知道它
Global.asax有一個Session屬性,它返回一個HttpSessionState實際上似乎工作正常的屬性(我最終將它注入到跟踪器中)..但我很好奇,我怎麼能從外部獲得對所
HttpSessionState使用對象的相同引用?Global.asax``Global.asax在此先感謝各位,感謝您的意見。:)
Global.asax 實現 HttpApplication - 當您在其中呼叫它時,您正在與它交談。
HttpApplication的 MSDN 文件詳細介紹瞭如何在 HttpHandler 中獲取它,然後訪問它的各種屬性。
然而
您的應用程序可以創建多個 HttpApplication 實例來處理並行請求,並且這些實例可以重複使用,因此僅以某種方式選擇它並不能保證您擁有正確的實例。
我還要注意一點 - 如果您的應用程序崩潰,則無法保證 session_end 將被呼叫,並且您將失去所有會話中的所有數據,這顯然不是一件好事。
我同意在每個頁面上記錄可能不是一個好主意,但可能是發生一些非同步日誌記錄的中途之家 - 你將細節發送到日誌記錄類,不時記錄你所追求的細節 - 仍然不是 100%如果應用程序崩潰,它是可靠的,但你不太可能失去一切。
為了更好地回答原始問題:
背景
每個頁面請求都會啟動一個新
Session對象,然後從您的會話儲存中擴充它。為此,它使用客戶端提供的 cookie 或特殊路徑構造(用於無 cookie 會話)。使用此會話標識符,它會查詢會話儲存並反序列化(這就是除 InProc 之外的所有提供程序都需要可序列化的原因)新會話對象。對於 InProc 提供程序,只需將它儲存在
HttpCache會話標識符鍵控中的引用交給您。這就是 InProc 提供程序在AppDomain回收時丟棄會話狀態的原因(也是多個 Web 伺服器無法共享 InProc 會話狀態的原因。這個新創建和膨脹的對像被卡在
Context.Items集合中,因此它在請求期間可用。然後,您對
Session對象所做的任何更改都會在對會話儲存的請求結束時通過序列化(或者在 InProc 的情況下,HttpCache條目被更新)進行持久化。由於
Session_End在沒有目前請求的情況下立即觸發,因此該對Session像在沒有可用資訊的情況下自動旋轉。如果使用 InProc 會話狀態,則過期HttpCache會觸發一個回調事件到您的Session_End事件中,因此會話條目可用,但仍然是最後儲存在HttpContext.Cache. 該值HttpApplication.Session通過內部方法(稱為ProcessSpecialRequest)針對屬性儲存,然後可用。在所有其他情況下,它在內部來自HttpContext.Current.Session值。你的答案
由於 Session_End 總是針對空上下文觸發,因此您應該始終在該事件中使用 this.Session 並將 HttpSessionState 對像傳遞給您的跟踪程式碼。在所有其他情況下,從跟踪程式碼中獲取
HttpContext.Current.Session然後傳遞給跟踪程式碼是非常好的。但是,不要讓跟踪程式碼到達會話上下文**。**我的答案
Session_End除非您知道您正在使用的會話儲存支持Session_End,否則不要使用,如果它true從SetItemExpireCallback. 唯一的開箱即用商店是InProcSessionState商店。Session_End可以編寫一個會話儲存,但如果有多個伺服器,誰將處理它的問題有點模棱兩可。