Quick Overview of ASP.NET Sessions
ASP.NET session state is maintained by using one of two underlying
mechanisms. The first is by using HTTP cookies. The idea behind HTTP
cookies is that when the client sends a request, the server sends back
a response with an HTTP Set-Cookie header that has a name/value pair in
it. For all subsequent requests to the same server, the client sends
the name/value pair in an HTTP Cookie header. The server then can use
the value to associate the subsequent requests with the initial
request. ASP.NET uses a cookie that holds a session ID to maintain
session state. Then that ID is used to find the corresponding instance
of the HttpSessionState class for that particular user. The HttpSessionState class provides just a generic collection in which you can store any data that you want.
The other mechanism that ASP.NET uses for maintaining session state
works without cookies. Some browsers do not support cookies or are not
configured to keep and send cookies. ASP.NET provides a mechanism for
getting around this problem by redirecting a request to a URL that has
the ASP.NET session ID embedded in it. When a request is received, the
embedded session ID is simply stripped out of the URL and is used to
find the appropriate instance of the session object. This works great
for browsers that are doing HTTP GET requests, but creates issues when
writing Microsoft® .NET code that consumes an XML Web service.
It should be noted that sometimes it makes sense to store state
information in cookies themselves instead of in the ASP.NET session
object. By avoiding the session object, you use fewer resources on the
server, and you do not have to worry about issues like locating a
specific instance of the session object across a Web farm, instances of
the session object being cleaned up because of a long delays between
requests, or session instances lingering around for no reason until
their timeout period expires. However, if you have data that includes
implementation information that you do not want to share with the
consumers of your service, or is private data that you do not want to
send across an unencrypted channel, or if the data would be impractical
to serialize into an HTTP header, then it may make sense to take
advantage of the HttpSessionState class in ASP.NET. The HttpSessionState class returns an index key that is used to map a particular user to an instance of the HttpSessionState class that holds information stored for that user. Both the ASP.NET HttpSessionState class and HTTP cookies are available to users writing ASP.NET Web services.
Why Use an HTTP Mechanism for Maintaining State in an XML Web Service?
There are many ways to maintain state between SOAP requests.
Certainly one feasible option would be to include something like the
ASP session ID in the SOAP header of your SOAP message. The problem is
that you have to: 1) still write the server side code yourself, and 2)
make sure your clients treat your session ID header like an HTTP cookie
and send it back to you with each request. There are certainly cases
where using the SOAP header approach makes a lot of sense, but there
are situations where using the HTTP approach can make sense as well.
ASP.NET session state is already done for you. The HttpSessionState
class is available for easily storing your session objects. Most HTTP
clients already understand that they must return the cookies that are
set by the server and HttpSessionState happens to support the
underlying transport most frequently used for SOAP communications—HTTP.
Thus it makes sense that using ASP.NET session support could be a smart
decision to meet many state management requirements.
Enabling Session Support on the Server
By default, ASP.NET session support for each Web method is turned
off. You must explicitly enable session support for each Web method
that wants to use session state. This is done by adding the EnableSession property to the WebMethod attribute of your function. The code for a Web method with the EnableSession property set to true, and which accesses the HttpSessionState object, is shown below.
<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
As you might expect, if you enable session support for one Web
method, that does not imply that it is enabled for another Web method.
In fact, the Context.Session property will be null if EnableSession is not explicitly set to True for a particular Web method.
Be aware that it is possible to disable sessions by way of a web.config setting, so that even if you use the EnableSession property in your WebMethod attribute, Context.Session will always be null. The /configuration/system.web/sessionState element
has a mode attribute that is used to configure how session state is
maintained for your ASP.NET application. By default the mode is set to
"InProc," which means that the HttpSessionState objects will
simply be held in the ASP.NET process'''' memory. If the mode is set to
"Off," then there will be no session state support in the ASP.NET
application.
From the HTTP server standpoint, the scope of an ASP.NET session is
that it lives within a given ASP.NET application. This means that the
same instance of the HttpSessionState class will be used for
all session-enabled ASP.NET requests within a single virtual directory
for a particular user. A request to a different virtual directory with
the same session ID cookie will result in ASP.NET being unable to find
the corresponding session object—because the session ID was set for a
different ASP.NET application. ASP.NET does not differentiate between
ASPX and ASMX requests as far as sessions are concerned, so you could
theoretically share session state between a Web method call and a
normal ASPX file. However, there are client-side issues that we will
look at in a little bit that might make this tricky.
When setting an HTTP cookie, you can associate an optional
expiration time with it. The expiration time indicates how long the
client should continue sending the cookie back to the server. If a
cookie is set without the optional expiration, it will only be returned
for the life of the process making the requests. For instance,
Microsoft® Internet Explorer will return the cookie until you close
that particular instance of your browser. The session ID cookies used
by ASP.NET do not have expiration times. Therefore, if multiple
processes on a client machine are making HTTP requests to your server,
then they will not share the same HttpSessionState object. This is true even if the two processes are running at the same time.
If you are making simultaneous Web service calls from the same
process, the requests will be serialized at the server so that only one
will execute at any one time. Unlike .ASPX pages that have support for
read-only access to the HttpSessionState object, which allows
for simultaneous processing of multiple requests, there is no such
capability with ASP.NET Web services. All Web method calls with
sessions enabled have read/write access and will be serialized within
each session.
Client-Side Issues
Successfully using the HttpSessionState capabilities in your
Web service does rely upon some assumptions about the consumers of your
Web service. First and foremost, if you are using the default HTTP
cookie mode of maintaining session state, then your clients must
support HTTP cookies. If you are using the cookieless mechanism for
supporting sessions, then your clients must be able and willing to
redirect their requests to the modified URLs with the session IDs in
them. As it turns out, this is not a trivial assumption, even with a
.NET client application.
Everything Works from the Browser
If you develop an ASP.NET Web service in Microsoft® Visual Studio®
.NET, the default debugging behavior is to launch Internet Explorer and
browse to your .ASMX file. This usually will result in a friendly HTML
interface for invoking your Web methods. This turns out to be a nice
way to debug your Web service code, and if you have set the EnableSession
property to True for your Web method, it tends to work out beautifully.
Even if you turn on cookieless session support, the browser client will
work perfectly, and your session will work in the manner that you
expect it to.
However, most Web service requests do not come from a browser. What
happens when you create a client application that uses the "Add Web
Reference" feature of the .NET Framework? Let''''s take a look at the
results.
Problems Using Add Web Reference
I created a simple XML Web service using the code snippet that we saw earlier. If you recall, the Web method is called IncrementSessionCounter and simply stores an integer in the HttpSessionState
object, increments it with each call, and returns the current value.
From the browser client, we see that the number increases by one with
each invocation as we expect.
Next, I created a simple Microsoft® Windows Form application and
added a Web reference for my Web service. The code for invoking my Web
service looks like this:
[1] [2] [3] 下一页
|