最近在ASP.NET MVC項目中碰到這樣的狀況:在一個controller中設置了Session,但在另外一個controller的構造函數中沒法獲取該Session,會報"System.NullReferenceException"錯誤。之因此這樣作是由於但願在controller構造函數中獲取Session值並賦值給一個全局變量,好讓該controller的多個action共享。html
起先覺得是ASP.NET State Service服務沒有開啓,或者是Web.config中sessionState節點配置不對,結果都不是。最終發現:在ASP.NET中,Session只存在於action中,在controller構造函數中獲取Session是行不通的。web
那麼,ASP.NET Session究竟是如何工做的?在ASP.NET MVC中action如何獲取Session呢?數據庫
爲何須要Session安全
ASP.NET頁面是"無狀態"的,這意味着每次向服務器發送一個請求,服務器都會生成一個該頁面的實例。但有時候,咱們但願在不一樣的頁面之間共享信息,好比購物車、用戶登陸等,因而,ASP.NET爲咱們提供了一個服務端的Session機制。服務器
Session是如何工做的session
服務端的Session機制是基於客戶端的,也就是說服務端的Session會保存每一個客戶端的信息到服務端內存中。具體過程是這樣的:
→客戶端向服務端發出請求
→服務端響應客戶端,並針對該客戶端建立Session和惟一的Session ID
→把Session ID做爲key, Session內容做爲value,以鍵值對形式存儲到Session State Provider中
→客戶端帶着專屬的Session ID再次向服務端請求
→服務端的Session機制根據客戶端的Session ID,從Session State Provider中取出內容返回給客戶端asp.net
優勢:
● 跨頁面維持用戶狀態、信息
● 使用方便,而且能存儲任何類型
● 能保存每一個客戶端的信息
● 安全的、透明的tcp
缺點:
● 由於Session是保存在服務端的內存中的,隨着客戶端請求的增多,頗有可能影響到性能
● 在Web.conig中,sessionState節點的mode屬性,若是設置爲"StateServer"或"SQLServer",就必須爲存儲到Session中的對象打上[Serializable]。這樣在存儲、讀取Session的時候,不斷地序列化和反序列化,也會影響到性能ide
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"中介紹的方式。
參考資料:
http://www.cnblogs.com/ghd258/archive/2006/02/28/339443.html
http://www.codeproject.com/Articles/32545/Exploring-Session-in-ASP-Net