Web services do not support session state by default. In most cases they should be designed to be stateless if you want to achieve high scalability. Sometimes, you can decide to manage state if you want to retain user-specific information or to optimize performance in a specific scenario. In this case, you need to use the EnableSession property, as shown:
<WebMethod(EnableSession:=True)> _
Public Function StateFulMethod() As DataSet
‘…
End Function
ASP.NET relies on HTTP cookies to support session state, because it is not a part of the SOAP specifications. The session cookie stores a session ID, and ASP.NET uses the session ID to associate the client with the session state on the server. However, there is no guarantee that the client will support cookies. ASP.NET state management will not work, and new session will be created with each new request, if the client does not support cookies. Unfortunately, your code has no way to identify this error condition.
You can create a simple web service to observe the potential problems with session state. It stores a single piece of personalized information (the book title) and allows you to retrieve it later:
Public Class StatefulService
Inherits System.Web.Services.WebService
<WebMethod(EnableSession := True)> _
Public Sub StoreBookTitle(bookTitle As String)
Session(“BookTitle”) = bookTitle
End Sub
<WebMethod(EnableSession := True)> _
Public Function GetBookTitle() As String
If Session(“BookTitle”) Is Nothing Then
Return “”
Else
Return DirectCast(Session(“BookTitle”), String)
End If
End Function
End Class
Two web methods StoreBookTitle() and GetBookTitle() provide the expected behavior if you test them by using the ASP.NET test page. That’s because web browsers support cookies without a hitch. The proxy class does not share this ability by default. You can see this problem in action if you add a reference to the StatefulService in the Windows client and then add a new button with the following code:
Private Sub CmdTestState_Click(sender As Object, e As System.EventArgs)
‘ Create the proxy.
Dim Proxy As New StatefulService()
‘ Set a book title.
Proxy.StoreBookTitle(“FIFTY SHADES OF GREY”)
‘ Try to retrieve the book title.
MessageBox.Show(“You set: ” & Proxy.GetBookTitle())
End Sub
This code does not work as you expect and the book title disappears in the message box.
You can resolve this problem, by preparing a web service proxy. You should use the proxy to accept the session cookie by creating a cookie container as instance of the System.Net.CookieContainer class:
Public Partial Class Form1
Inherits System.Windows.Forms.Form
Private CookieContainer As New System.Net.CookieContainer()
‘….
End Class
Now you should attach this cookie container to the proxy class before you call ant web method:
Private Sub cmdTestState_Click(sender As Object, e As System.EventArgs)
Dim Proxy As New StatefulService()
Proxy.CookieContainer = CookieContainer
Proxy.StoreBookTitle(“FIFTY SHADES OF GREY”)
MessageBox.Show(“You set: ” & Proxy.GetBookTitle())
End Sub
In this case both web method calls use the same session, and the book title appears in the message box.
You need to keep the cookie container around as long as you need to keep the session cookie.
Important notes:
1. Web services are destroyed after every method call and they don’t provide a natural mechanism for storing state information.
2. You can use the Session collection to compensate for this limitation, but this approach raises the following complications:
a. Session state will disappear when the session times out. The client will have no way of knowing when the session times out, which means the web service may behave unpredictably.
b. Session state is tied to a specific user, not to a specific class or object. This can cause problems if the same client wants to use the same web service in two different ways or creates two instances of the proxy class at once.
c. Session state is maintained only if the client preserves the session cookie. The state management you use in a web service won’t work if the client fails to take these steps.