top
Loading...
WebService中保持ASP.net的狀態

簡介

網絡程序開發者們遇到的最普遍的問題就是如何在無狀態的基于HTTP協議的交互中保持狀態信息。有許多聰明的辦法可以解決HTTP協議的無狀態問題,例如對每個請求重復發送應用程序數據包、使用HTTP認證機制來將請求映射到特定的用戶、使用Cookie來存儲一系列請求的狀態等。在ASP.net技術中提供了一個非常有效的方案來保持狀態,該方案隱藏了所有高難度的,具有挑戰性的工作的細節,用戶只需簡單地使用System.Web.SessionState.HttpSessionState類。同時,你也可以像在ASP.net程序的Web頁面(.aspx)中那樣在Web Service的方法中使用這個類,只有一點小小的不同。

ASP.net的Session對象概述

ASP.net的Session狀態信息是通過兩個機制保持。其一是使用Cookie。當客戶端發送一個請求到服務器端時,服務器將發回一個附加HTTP Set-Cookie頭的響應信息,而Cookie的值就是以鍵/值對的形式保存在該信息里邊。在對同一服務器的所有的同步請求中,客戶端在HTTP Cookie頭中發送Cookie鍵/值對。然后服務器可以將并發的請求同初始的請求對應起來。ASP.net使用一個保存會話的ID的cookie來保持會話狀態。該ID標識被用來為特定的用戶找到與其對應的HttpSessionState類的實例。類HttpSessionState僅僅提供了一個通用的數據集,你可以在其中保存你需要的任何信息。

ASP.net用來保持狀態的另外一種機制是無須使用Cookie。一些瀏覽器被用戶設置為禁止使用Cookie或者干脆就不支持Cookie,ASP.net提供了一種機制來解決這個問題,它的主要原理是將一個請求重定向到一個包含ASP.net狀態ID的URL。當該請求被接受到時,這個嵌在URL中的ID被截取下來,服務器通過該ID找到合適的HttpSessionState類的實例。這種方式在HTTP協議的使用GET方式的請求中工作的很好,但是在.net的XML Web Service代碼中會出現問題。

必須指出的是,有些時候把信息直接存儲在Cookie中要比存儲在Session中更好。避免使用Session可以節省服務器資源,而且你也無須考慮一些煩人的問題,比如定位一個特定的Session對象、Session對象因為請求的長時間的延遲而被移除或者在服務器上沒必要地保留直到過期。然而,如果你有一些包含你不希望與你提供的服務的使用者共享的執行信息,或者有一些你不希望通過未加密的信道傳輸的私有數據,或者你認為將這些數據插入HTTP協議頭中是不切實際的,那么你就應該使用ASP.net中的HttpSessionState,它將使你輕松解決這些問題。HttpSessionState類返回一個索引鍵,用以將一個特定的用戶映射到一個為該用戶保存信息的HttpSessionState類的實例。總之,無論是ASP.net的HttpSessionState類還是HTTP的Cookie都可以在ASP.net Web Service中使用。

為什么要在XML Web Service中使用基于HTTP的機制來實現狀態保持呢?

在SOAP請求中有許多方法來保持狀態。一個切實可行的方法就是在SOAP頭中包含一些像ASP中的會話ID的信息,然而問題在于你不得不:1) 仍然要自己編寫服務器端代碼,并且 2) 確信你的客戶會像對待HTTP Cookie一樣對待你的包含會話ID的SOAP頭并且將它附加到每個請求中回傳給你。當然有很多時候使用SOAP頭的方法會很方便,但是也有很多時候還不如使用基于HTTP協議的方法。

很容易在ASP.net中使用Session來保持狀態信息,HttpSessionState類為你封裝了存儲Session狀態的細節問題。絕大多數的客戶端已經能夠明白他們必須返回服務器設置的cookie,而且HttpSessionState類也支持在SOAP通信中常用的底層傳輸。因此,很明顯,使用ASP.net的Session機制會是滿足狀態控制要求的明智的選擇。

使服務器支持Session

在ASP.net中,對Web方法的狀態支持默認是關閉的,你必須為每個要使用Session狀態的Web方法顯式地激活Session支持。激活Session支持的方法是添加一個EnableSession選項到你的函數的WebMethod屬性中,并且將其值設置為true。下面的代碼演示了如何激活Session并且在方法中訪問Session狀態信息。

[VB.net]

<WebMethod(EnableSession:=True)> _
Public Function IncrementSessionCounterX() As Integer
Dim counter As Integer
If Context.Session("Counter") Is Nothing Then
counter = 1
Else
counter = Context.Session("Counter") + 1
End If
Context.Session("Counter") = counter
Return counter
End Function

如你所料,如果你為一個Web方法激活了Session支持,并不意味著其它的Web方法的Session支持也被激活。事實上,如果Web方法的EnableSession選項沒有被顯式地設置為true,那么Context.Session屬性的值將是null。

假設通過設置web.config文件禁止session,那么即使你在WebMethod屬性中使用了EnableSession選項,Context.Session的值也將一直是null。web.config文件中的/configuration/system.web/sessionState項有一個mode參數,它決定了你的ASP.net程序使用何種方法來保持Session狀態。該參數默認設置為“InProc”,這時HttpSessionState對象將簡單地保存在ASP.net進程的內存區。如果被設置為“Off”,那么ASP.net程序的Session支持就被關閉了。

從服務器端看來,ASP.net的session狀態的有效范圍僅僅是某一個給定的ASP.net應用程序,這就意味著一個HttpSessionState類的實例只能被一個特定用戶向某一個虛擬目錄發出的所有Session被激活的ASP.net請求所使用,也就是說,使用同一個會話ID的向其它的虛擬目錄的請求將導致ASP.net不能找到對應的session對象——因為會話ID不是為該ASP.net應用程序設定的。ASP.net并不區分對ASPX和ASMX文件的請求,直到該請求需要使用Session對象,因此,理論上你可以在一個Web方法調用和一個普通的ASPX文件之間共享Session狀態信息。然而,我們將看到也有些客戶端的問題使這個想法變得不那么容易實現。

當設置一個HTTP cookie,你可以指定其過期時間。過期時間指定在多久的時間內,客戶端應該將該cookie回傳給服務器。如果一個cookie沒有被設置過期時間,那么它僅僅在該進程處理請求的時間內被回傳。例如,IE將一直回傳cookie,除非你關閉了瀏覽器的特定窗口。ASP.net的用來保存會話ID的Cookie沒有過期時間,因此,如果一臺客戶機上的多個進程向你的服務器上發送HTTP請求,它們也不會共享同一個HttpSessionState對象,甚至兩個進程同時運行也是這樣。

如果你要處理來自同一個進程的并發的Web Service調用,那么這些請求將在服務器上被排序,從而使得在某一時刻只有一個請求被執行。ASP.net的Web Service不像普通.ASPX頁面,支持允許多請求的并發進程的對HttpSessionState對象的只讀訪問,所有Session被激活的Web方法調用都具有read/write訪問的權限,因此必須對之進行排序。

作者:http://www.zhujiangroad.com
來源:http://www.zhujiangroad.com
北斗有巢氏 有巢氏北斗