ASP.NET MVC中的Session以及處理方式
最近在ASP.NET MVC項目中碰到這樣的情況:在一個controller中設置了Session,但在另一個controller的構造函數中無法獲取該Session,會報"System.NullReferenceException"錯誤。之所以這樣做是因為希望在controller構造函數中獲取Session值並賦值給一個全局變量,好讓該controller的多個action共享。
起先以為是ASP.NET State Service服務沒有開啟,或者是Web.config中sessionState節點配置不對,結果都不是。最終發現:在ASP.NET中,Session只存在於action中,在controller構造函數中獲取Session是行不通的。
那么,ASP.NET Session到底是如何工作的?在ASP.NET MVC中action如何獲取Session呢?
為什么需要Session
ASP.NET頁面是"無狀態"的,這意味着每次向服務器發送一個請求,服務器都會生成一個該頁面的實例。但有時候,我們希望在不同的頁面之間共享信息,比如購物車、用戶登錄等,於是,ASP.NET為我們提供了一個服務端的Session機制。
Session是如何工作的
服務端的Session機制是基於客戶端的,也就是說服務端的Session會保存每個客戶端的信息到服務端內存中。具體過程是這樣的:
→客戶端向服務端發出請求
→服務端響應客戶端,並針對該客戶端創建Session和唯一的Session ID
→把Session ID作為key, Session內容作為value,以鍵值對形式存儲到Session State Provider中
→客戶端帶着專屬的Session ID再次向服務端請求
→服務端的Session機制根據客戶端的Session ID,從Session State Provider中取出內容返回給客戶端
優點:
● 跨頁面維持用戶狀態、信息
● 使用方便,並且能存儲任何類型
● 能保存每個客戶端的信息
● 安全的、透明的
缺點:
● 因為Session是保存在服務端的內存中的,隨着客戶端請求的增多,很有可能影響到性能
● 在Web.conig中,sessionState節點的mode屬性,如果設置為"StateServer"或"SQLServer",就必須為存儲到Session中的對象打上[Serializable]。這樣在存儲、讀取Session的時候,不斷地序列化和反序列化,也會影響到性能
Session的Mode
在Web.config中,sessionState節點有一個mode屬性,它的屬性值代表了Session的Mode。包括:
● InProc
● StateServer
● SQLServer
● Custom
● Off
每一種Mode的設置,會影響到Session機制采用哪種Session State Provider。
□ Off
如果我們想讓Session失效:
<system.web>
<sessionState mode="off" />
</sytem.web>
□ InProc
這也是ASP.NET Session機制所選用的默認Mode,在該模式下,只保存當前應用程序域的數據。如果重啟服務器,Session保存的數據會全部丟失。
<system.web>
<sessionState mode="InProc" timeout="30" />
</system.web>
表示Session的有效期是30分鍾。對於一些小網站或者數據量不大的時候,選用這個模式是比較好的。
優點:
● 由於是把Session數據保存在內存中的,所以,獲取數據非常快
● 沒有序列化和反序列化的要求
缺點:
● 如果應用程序域被丟棄、重啟,Session數據會丟失
● 數據量大的時候,消耗過多的內存,影響性能
□ StateServer
選用此選項,意味着把Session的工作交給了當前應用程序域之外的asp.net_state.exe服務,這是一個獨立於IIS之外的Windows服務。如果想啟動該服務,可以通過打開“控制面板--管理工具--服務”,找到ASP.NET State Service這個服務,將其設為自動啟動。
即使重啟ASP.NET進程,Session依然有效,這是StateServer模式的優點。此模式的缺點是涉及過多的序列化和反序列化。
<system.web>
<sessionState mode="StateServer" stateConnectionSting="tcpip=127.0.0.1:42424" stateNetworkTimeout="40" />
</sytem.web>
● 127.0.0.1 表示默認選用本機
● 42424 表示默認端口
● stateNetworkTimeout用來設置服務器響應、等待客戶端請求的時間,默認是10秒,這里設置為40秒
如果想修改StateServer的默認設置,可以在asp.net_state.exe對應的注冊表中修改。
□ SQLServer
選用此模式,Session數據被序列化,並被保存到SQL Server數據庫中。為了讓Sql Server配合此模式,需要做如下:
→查看版本位置,比如在:C:\Windows\Microsoft.NET\Framework\v4.0.30319
→輸入如下命令
-ssadd 表示在SQL Server中添加session state
-sstype p 表示Persisted
-S 表示服務器名
-U 表示SQL Server用戶名
-P 表示SQL Server密碼
→數據庫中多了ASPState數據庫,Session數據將被保存到此數據庫的相關表中
優點:
● 在重啟IIS后,Session數據不會受影響
● 最安全的Session處理方式
缺點:
● 處理相對緩慢
● 過多的序列化和反序列化
□ Custom
自定義Session機制,通過繼承SessionStateStoreProviderBase類,實現ISessionIDManager接口,等等。
Session的Event
Session的事件有2個:Session_Start和Session_End。可以在global.asax全局文件中對這2個事件做處理。
void Session_Start(object sender, EventArgs e)
{
//TODO
}
void Session_End(object sender, EventArgs e)
{
// TODO
}
ASP.NET MVC處理Session的2種方式
如果處理用戶登錄,可以使用"MVC擴展ValueProvider,通過實現IValueProvider接口創建SessionValueProvider"中介紹的方式。如果處理購物車,可以使用"http://www.cnblogs.com/darrenji/p/3813109.html"中介紹的方式。