asp.net|web 下一步,我建立了一個簡單的WinForm應用程式,並且將上述的Web Service添加到Web引用中。下面就是調用我的Web Service的代碼:
' 這裡並沒有與Session打交道
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim proxy As New localhost.Service1()
Dim ret As Integer
ret = proxy.IncrementSessionCounter()
Label1.Text = "Result: " & CStr(ret)
End Sub
當我第一次調用Web Service時,一切正常,Web方法返回1,這就是那個Session變數的應有的初始值。現在我點擊Button1來再次調用這個Web方法,我希望看到的傳回值是2。可惜的是,無論我點擊多少次Button1,傳回值一直都是1。
你也許會懷疑原因就是我每次都建立了一個新的proxy類的執行個體去調用Web方法,因此每次我點擊按鈕,都會丟失上一次調用時的cookie。不幸的是,即使你將proxy類的初始化代碼移到表單的建構函式中,然後對每次Web方法調用使用同一個proxy類的執行個體,你還是不可能看到傳回值有增加的跡象。
問題在於cookie。Web Service代碼並未從調用請求中發現有效會話ID,因此它每次被調用都建立一個全新的HttpSessionState對象,並且返回它的初始值1。因為作為用戶端的proxy類是從類System.Web.Service.Protocols.SoapHttpClientProtocol繼承的,它不包含System.Net.CookieContainer類的執行個體,因此,沒有地方來存放返回的cookie。為瞭解決這個問題,我對代碼做了如下一些修改:
' 使用了ASP.NET的session
' 但是並不是無Cookie的session.
Private Cookies As System.Net.CookieContainer
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim proxy As New localhost.Service1()
Dim ret As Integer
' 為proxy類設定cookie容器
If Cookies Is Nothing Then
Cookies = New System.Net.CookieContainer()
End If
proxy.CookieContainer = Cookies
ret = proxy.IncrementSessionCounter()
Label1.Text = "Result: " & CStr(ret)
End Sub
現在代碼工作正常了!每點擊一次Button1,我都可以看到傳回值增加1。注意到我並不是在函數中聲明變數Cookies的,它是表單類的一個私人成員,因為如果希望每次都返回同一個會話ID給伺服器的話,就必須在每次請求中使用CookieContainer類的同一個執行個體。這就解釋了為什麼SoapHttpClientProtocol類預設不自動地設定的cookie容器。正應為此,你可以在多個SoapHttpClientProtocol類的執行個體中共用一個cookie容器,而不是為其每個執行個體自動地建立一個新的cookie容器。
無cookie的Session從Web Service的開發人員的角度來看,你可以想到相當多的人在試圖使用你的Web服務時忘記在用戶端代理類中添加Cookie容器。聰明的開發人員或許靈光一閃,就會發現無cookie的Session應該可以出色地解決這個問題。如果將web.config檔案中sessionState元素的cookieless參數設定為“true”,你將會發現,通過瀏覽器介面調用Web方法時,session變數工作正常,但是如果你在Visual Studio.net中通過“添加Web引用”來調用它時,依然存在著一些問題。