Working with Session s State

 

Working with Session's State

Now that you have grabbed hold of the session-state basics, we can sharpen our skills by looking into more technically relevant aspects of session-state management. Handling session-state is a task that can be outlined in three steps: assigning a session ID, obtaining session data from a provider, and stuffing it into the context of the page. As mentioned, the session-state module governs the execution of all these tasks. In doing so, it takes advantage of a couple of additional components: the session ID generator and session-state provider. In ASP.NET 2.0, both can be replaced with custom components, as we'll discuss later. For now, let's tackle some of the practical issues you face when working with session state.

Identifying a Session

Each active ASP.NET session is identified using a 120-bit string made only of URL-allowed characters. Session IDs are guaranteed to be unique and randomly generated to avoid data conflicts and prevent malicious attacks. Obtaining a valid session ID algorithmically from an existing ID is virtually impossible. In ASP.NET 1.x, the generator of the session ID is a system component buried in the framework and invisible from outside. In ASP.NET 2.0, it has become a customizable component that developers can optionally replace.

Note 

An old proverb reminds us that nothing should be done only because it is doable. This motto is particularly apt here as we talk about parts of the session-state management that are customizable in ASP.NET 2.0. These subsystems, such as the session ID generator, should be customized only with good reason and with certainty that it won't make things worse or lower the level of security. I'll return to this point in a moment with more details.

Generating the Session ID

A session ID is 15 bytes long by design (15 8 = 120 bits). The session ID is generated using the Random Number Generator (RNG) cryptographic provider. The service provider returns a sequence of 15 randomly generated numbers. The array of numbers is then mapped to valid URL characters and returned as a string.

If the session contains nothing, a new session ID is generated for each request and the session state is not persisted to the state provider. However, if a Session_Start handler is used, the session state is always saved, even if empty. For this reason, and especially if you're not using the in-process session provider, define Session_Start handlers with extreme care and only if strictly necessary.

In contrast, the session ID remains the same after a nonempty session dictionary times out or is abandoned. By design, even though the session state expires, the session ID lasts until the browser session is ended. This means that the same session ID is used to represent multiple sessions over time as long as the browser instance remains the same.

Session Cookies

The SessionID string is communicated to the browser and then returned to the server application in either of two ways: using a cookie or a modified URL. By default, the session-state module creates an HTTP cookie on the client, but a modified URL can be used especially for cookieless browsers with the SessionID string embedded. Which approach is taken depends on the configuration settings stored in the application's web.config file. By default, session state uses cookies.

A cookie is really nothing more than a text file placed on the client's hard disk by a Web page. In ASP.NET, a cookie is represented by an instance of the HttpCookie class. Typically, a cookie has a name, a collection of values, and an expiration time. In addition, you can configure the cookie to operate on a particular virtual path and over secure connections (for example, HTTPS).

Important 

ASP.NET 2.0 takes advantage of the HTTP-only feature for session cookies on the browsers that supports it. For example, it is supported on Microsoft Internet Explorer 6.0 SP1 or with Windows XP SP2 installed. The HTTP-only feature prevents cookies from being available to client-side script, thus raising a barrier against potential cross-site scripting attacks aimed at stealing session IDs.

When cookies are enabled, the session-state module actually creates a cookie with a particular name and stores the session ID in it. The cookie is created as shown in the following pseudocode:

HttpCookie sessionCookie; sessionCookie = new HttpCookie("ASP.NET_SessionId", sessionID); sessionCookie.Path = "/"; 

ASP.NET_SessionId is the name of the cookie, and the sessionID string is its value. The cookie is also associated with the root of the current domain. The Path property describes the relative URL that the cookie applies to. A session cookie is given a very short expiration term and is renewed at the end of each successful request. The cookie's Expires property indicates the time of day on the client at which the cookie expires. If not explicitly set, as is the case with session cookies, the Expires property defaults to DateTime.MinValue that is, the smallest possible unit of time in the .NET Framework.

Note 

A server-side module that needs to write a cookie adds an HttpCookie object to the Response.Cookies collection. All cookies found on the client and associated with the requested domain are uploaded and made available for reading through the Request.Cookies collection.

Cookieless Sessions

For the session state to work, the client must be able to pass the session ID to the server application. How this happens depends on the configuration of the application. ASP.NET applications define their session-specific settings through the <sessionState> section of the configuration file. To decide about the cookie support, you set the cookieless attribute to one of the values in Table 13-7. The listed values belong to the HttpCookieMode enumerated type.

Table 13-7: HttpCookieMode Enumerated Type

Mode

Description

AutoDetect

Use cookies only if the requesting browser supports cookies.

UseCookies

Use cookies to persist the session ID regardless of whether the browser supports cookies. This is the default option.

UseDeviceProfile

Base the decision on the browser's capabilities as listed in the device profile section of the configuration file.

UseUri

Store the session ID in the URL regardless of whether the browser supports cookies. Use this option if you want to go cookieless no matter what.

When AutoDetect is used, ASP.NET will query the browser to determine whether it supports cookies. If the browser supports cookies, the session ID will be stored in a cookie; otherwise, the session ID will be stored in the URL. When UseDeviceProfile is set, on the other hand, the effective capabilities of the browser are not checked. For the session HTTP module to make the decision about cookies or URL, the declared capabilities of the browser are used as they result from the SupportsRedirectWithCookie property of the HttpBrowserCapabilities object. Note that even though a browser can support cookies, a user might have disabled cookies. In this case, session state won't work properly.

Note 

In ASP.NET 1.x, you have fewer options to choose from. The cookieless attribute of the <sessionState> section can accept only a Boolean value. To disable cookies in sessions, you set the attribute to true.

With cookie support disabled, suppose that you request a page at the following URL:

What is displayed in the browser's address bar is slightly different and now includes the session ID, as shown here:

When instantiated, the session-state module checks the value of the cookieless attribute. If the value is true, the request is redirected (HTTP 302 status code) to a modified virtual URL that includes the session ID just before the page name. When processed again, the request embeds the session ID. A special ISAPI filter the aspnet_filter.exe component preprocesses the request, parses the URL, and rewrites the correct URL if it incorporates a session ID. The detected session ID is also stored in an extra HTTP header named AspFilterSessionId and retrieved later.

Issues with Cookieless Sessions

Designed to make stateful applications also possible on a browser that does not support cookies or on one that does not have cookies enabled, cookieless sessions are not free of issues. First, they cause a redirect when the session starts and whenever the user follows an absolute URL from within an application's page.

When cookies are used, you can clear the address bar, go to another application, and then return to the previous one and retrieve the same session values. If you do this when session cookies are disabled, the session data is lost. This feature is not problematic for postbacks, which are automatically implemented using relative URLs, but it poses a serious problem if you use links to absolute URLs. In this case, a new session will always be created. For example, the following code breaks the session:

<a runat="server" href="/test/sessions.aspx">Click</a> 

Is there a way to automatically mangle absolute URLs in links and hyperlinks so that they incorporate session information? You can use the following trick, which uses the ApplyAppPathModifier method of the HttpResponse class:

<a href='<% =Response.ApplyAppPathModifier("test/page.aspx")%>' >Click</a> 

The ApplyAppPathModifier method takes a string representing a relative URL and returns an absolute URL, which embeds session information. This trick is especially useful when you need to redirect from an HTTP page to an HTTPS page, where the full, absolute address is mandatory. Note that ApplyAppPathModifier returns the original URL if session cookies are enabled and if the path is an absolute path.

Caution 

You can't use <% %> code blocks in server-side expressions that is, expressions flagged with the runat=server attribute. It works in the preceding code because the <a> tag is emitted verbatim, being devoid of the runat attribute.

Cookieless Sessions and Security

Another issue regarding the use of cookieless sessions is connected with security. Session hijacking is one of the most popular types of attacks and consists of accessing an external system through the session ID generated for another, legitimate user. Try this: set your application for work without cookies and visit a page. Grab the URL with the session ID as it appears in the browser's address bar, and send it immediately in an e-mail to a friend. Have your friend paste the URL in his or her own machine and click Go. Your friend will gain access to your session state as long as the session is active. The session ID is certainly not well-protected information (and probably couldn't work otherwise). For the safety of a system, an unpredictable generator of IDs is key because it makes it difficult to guess a valid session ID. With cookieless sessions, the session ID is exposed in the address bar and visible to all. For this reason, if you are storing private or sensitive information in the session state, it is recommended that you use Secure Sockets Layer (SSL) or Transport Layer Security (TLS) to encrypt any communication between the browser and server that includes the session ID.

In addition, you should always provide users the ability to log out and call the Abandon method when they think security has been breached in this way. This contrivance reduces the amount of time available for anybody getting to use your session ID to exploit data stored in the session state. And, speaking of security, it is important that you configure the system to avoid the reuse of expired session IDs when cookieless sessions are used. This behavior is configurable in ASP.NET 2.0 through the <sessionState> section, as you can read in the following section.

Configuring the Session State

The <sessionState> section has grown significantly in the transition from ASP.NET 1.x to ASP.NET 2.0. Here's how it looks now:

<sessionState     mode="Off|InProc|StateServer|SQLServer|Custom"     timeout="number of minutes"     cookieName="session cookie name"     cookieless="http cookie mode"     regenerateExpiredSession     sqlConnectionString="sql connection string"     sqlCommandTimeout="number of seconds"     allowCustomSqlDatabase="true|false"     useHostingIdentity="true|false"     partitionResolverType=""     sessionIDManagerType="custom session ID generator"     stateConnectionString="tcpip=server:port"     stateNetworkTimeout="number of seconds"     customProvider="custom provider name">     <providers>        ...    </providers> </sessionState> 

Table 13-8 details goals and characteristics of the various attributes. Note that only mode, timeout, stateConnectionString, and sqlConnectionString are identical to ASP.NET 1.x. The attribute cookieless also exists in ASP.NET 1.x but accepts Boolean values. All the others are new in ASP.NET 2.0.

Table 13-8: <sessionState> Attributes

Mode

Description

allowCustomSqlDatabase

If true, enables specifying a custom database table to store session data instead of using the standard ASPState.

Cookieless

Specifies how to communicate the session ID to clients.

cookieName

Name of the cookie, if cookies are used for session IDs.

customProvider

The name of the custom session-state store provider to use for storing and retrieving session-state data.

mode

Specifies where to store session state.

partitionResolverType

Indicates type and assembly of the partition resolver component to be loaded to provide connection information when session state is working in SQLServer or StateServer mode. If a partition resolver can be correctly loaded, sqlConnectionString and stateConnectionString attributes are ignored.

regenerateExpiredSessionId

When a request is made with a session ID that has expired, if this attribute is true, a new session ID is generated; otherwise, the expired one is revived. The default is false.

sessionIDManagerType

Null by default. If set, it indicates the component to use as the generator of session IDs.

sqlCommandTimeout

Specifies the number of seconds a SQL command can be idle before it is canceled. The default is 30.

sqlConnectionString

Specifies the connection string to SQL Server.

stateConnectionString

Specifies the server name or address and port where session state is stored remotely.

stateNetworkTimeout

Specifies the number of seconds the TCP/IP network connection between the Web server and the state server can be idle before the request is canceled. The default is 10.

timeout

Specifies the number of minutes a session can be idle before it is abandoned. The default is 20.

useHostingIdentity

True by default. It indicates that the ASP.NET process identity is impersonated when accessing a custom state provider or the SQLServer provider configured for integrated security.

In addition, the child <providers> section lists custom session-state store providers. ASP.NET session state is designed to enable you to easily store user session data in different sources, such as a Web server's memory or SQL Server. A store provider is a component that manages the storage of session-state information and stores it in alternative media (for example, Oracle) and layout. We'll return to this topic later in the chapter.

Lifetime of a Session

The life of a session state begins only when the first item is added to the in-memory dictionary. The following code demonstrates how to modify an item in the session dictionary. "MyData" is the key that uniquely identifies the value. If a key named "MyData" already exists in the dictionary, the existing value is overwritten:

Session["MyData"] = "I love ASP.NET"; 

The Session dictionary generically contains object types; to read data back, you need to cast the returned values to a more specific type:

string tmp = (string) Session["MyData"]; 

When a page saves data to Session, the value is loaded into an in-memory dictionary an instance of an internal class named SessionDictionary. (See Figure 13-2.) Other concurrently running pages cannot access the session until the ongoing request completes.

The Session_Start Event

The session startup event is unrelated to the session state. The Session_Start event fires when the session-state module is servicing the first request for a given user that requires a new session ID. The ASP.NET runtime can serve multiple requests within the context of a single session, but only for the first of them does Session_Start fire.

A new session ID is created and a new Session_Start event fires whenever a page is requested that doesn't write data to the dictionary. The architecture of the session state is quite sophisticated because it has to support a variety of state providers. The overall schema entails that the content of the session dictionary is serialized to the state provider when the request completes. However, to optimize performance, this procedure really executes only if the content of the dictionary is not empty. As mentioned earlier, though, if the application defines a Session_Start event handler, the serialization takes place anyway.

The Session_End Event

The Session_End event signals the end of the session and is used to perform any cleanup code needed to terminate the session. Notice, though, that the event is supported only in InProc mode that is, only when the session data is stored in the ASP.NET worker process.

For Session_End to fire, the session state has to exist first. That means you have to store some data in the session state and you must have completed at least one request. When the first value is added to the session dictionary, an item is inserted into the ASP.NET cache the aforementioned Cache object that we'll cover in detail in the next chapter. The behavior is specific to the in-process state provider; neither the out-of-process state server nor the SQL Server state server work with the Cache object.

However, much more interesting is that the item added to the cache only one item per active session is given a special expiration policy. You'll also learn more about the ASP.NET cache and related expiration policies in the next chapter. For now, suffice it to say that the sessionstate item added to the cache is given a sliding expiration, with the time interval set to the session timeout. As long as there are requests processed within the session, the sliding period is automatically renewed. The session-state module resets the timeout while processing the EndRequest event. It obtains the desired effect by simply performing a read on the cache! Given the internal structure of the ASP.NET Cache object, this evaluates to renewing the sliding period. As a result, when the cache item expires, the session has timed out.

An expired item is automatically removed from the cache. As part of the expiration policy for this item, the state-session module also indicates a remove callback function. The cache automatically invokes the remove function which, in turn, fires the Session_End event.

Note 

The items in Cache that represent the state of a session are not accessible from outside the system.web assembly and can't even be enumerated, as they are placed in a system-reserved area of the cache. In other words, you can't programmatically access the data resident in another session or even remove it.

Why Does My Session State Sometimes get Lost?

Values parked in a Session object are removed from memory either programmatically by the code or by the system when the session times out or is abandoned. In some cases, though, even when nothing of the kind seemingly happens, the session state gets lost. Is there a reason for this apparently weird behavior?

When the working mode is InProc, the session state is mapped in the memory space of the AppDomain in which the page request is being served. In light of this, the session state is subject to process recycling and AppDomain restarts. The ASP.NET worker process is periodically restarted to maintain an average good performance; when this happens, the session state is lost. Process recycling depends on the percentage of memory consumption and maybe the number of requests served. Although cyclic, no general estimate can be made regarding the interval of the cycle. Be aware of this when designing your session-based, in-process application. As a general rule, bear in mind that the session state might not be there when you try to access it. Use exception handling or recovery techniques as appropriate for your application.

Consider that some antivirus software might be marking the web.config or global.asax file as modified, thus causing a new application to be started and subsequently causing the loss of the session state. This holds true also if you or your code modify the timestamp of those files or alter the contents of one of the special folders such as Bin or App_Code.

Note 

What happens to the session state when a running page hits an error? Will the current dictionary be saved or is it just lost? The state of the session is not saved if, at the end of the request, the page results in an error that is, the GetLastError method of the Server object returns an exception. However, if in your exception handler you reset the error state by calling Server.ClearError, the values of the session are saved regularly as if no error ever occurred.

Persist Session Data to Remote Servers

The session-state loss problem that we mentioned earlier for InProc mode can be neatly solved by employing either of the two predefined out-of-process state providers StateServer and SQLServer. In this case, though, the session state is held outside the ASP.NET worker process and an extra layer of code is needed to serialize and deserialize it to and from the actual storage medium. This operation takes place whenever a request is processed.

The need of copying session data from an external repository into the local session dictionary might tax the state management process to the point of causing a 15 percent to 25 percent decrease in performance. Notice, though, that this is only a rough estimate, and it's closer to the minimum impact rather than to the maximum impact. The estimate, in fact, does not fully consider the complexity of the types actually saved into the session state.

Caution 

When you get to choose an out-of-process state provider (for example, StateServer and SQLServer), be aware that you need to set up the run-time environment before putting the application in production. This means either starting a Windows service for StateServer or configuring a database for SQLServer. No preliminary work is needed if you stay with the default, in-process option.

State Serialization and Deserialization

When you use the InProc mode, objects are stored in the session state as live instances of classes. No real serialization and deserialization ever takes place, meaning that you can actually store in Session whatever objects (including COM objects) you have created and access them with no significant overhead. The situation is less favorable if you opt for an out-of-process state provider.

In an out-of-process architecture, session values are to be copied from the native storage medium into the memory of the AppDomain that processes the request. A serialization/deserialization layer is needed to accomplish the task and represents one of the major costs for out-of-process state providers. How does this affect your code? First, you should make sure that only serializable objects are ever stored in the session dictionary; otherwise, as you can easily imagine, the session state can't be saved.

To perform the serialization and deserialization of types, ASP.NET uses two methods, each providing different results in terms of performance. For basic types, ASP.NET resorts to an optimized internal serializer; for other types, including objects and user-defined classes, ASP.NET makes use of the .NET binary formatter, which is slower. Basic types are string, DateTime, Guid, IntPtr, TimeSpan, Boolean, byte, char, and all numeric types.

The optimized serializer an internal class named AltSerialization employs an instance of the BinaryWriter object to write out one byte to denote the type and then the value. While reading, the AltSerialization class first extracts one byte, detects the type of the data to read, and then resorts to a type-specific method of the BinaryReader class to take data. The type is associated to an index according to an internal table, as shown in Figure 13-4.


Figure 13-4: The serialization schema for basic types that the internal AltSerialization class uses.

Note 

While Booleans and numeric types have a well-known size, the length of a string can vary quite a bit. How can the reader determine the correct size of a string? The BinaryReader.ReadString method exploits the fact that on the underlying stream the string is always prefixed with the length, encoded as an integer seven bits at a time. Values of the DateTime type, on the other hand, are saved by writing only the total number of ticks that form the date and are read as an Int64 type.

As mentioned, more complex objects are serialized using the relatively slower BinaryFormatter class as long as the involved types are marked as serializable. Both simple and complex types use the same stream, but all nonbasic types are identified with the same type ID. The performance-hit range of 15 percent to 25 percent is a rough estimate based on the assumption that basic types are used. The more you use complex types, the more the overhead grows and reliable numbers can be calculated only by testing a particular application scenario.

In light of this, if you plan to use out-of-process sessions, make sure you store data effectively. For example, if you need to persist an instance of a class with three string properties, performancewise you are probably better off using three different slots filled with a basic type rather than one session slot for which the binary formatter is needed. Better yet, you can use a type converter class to transform the object to and from a string format. However, understand that this is merely a guideline to be applied case by case and with a grain of salt.

Caution 

In classic ASP, storing an ADO Recordset object in the session state was a potentially dangerous action because of threading issues. Fortunately, in ASP.NET no thread-related issues exist to cause you to lose sleep. However, you can't just store any object to Session and be happy. If you use an out-of-process scheme, you ought to pay a lot of attention to storing DataSet objects. The reason has to do with the serialization process of the DataSet class. Because the DataSet is a complex type, it gets serialized through the binary formatter. The serialization engine of the DataSet, though, generates a lot of XML data and turns out to be a serious flaw, especially for large applications that store a large quantity of data. In fact, you can easily find yourself moving megabytes of data for each request. Just avoid DataSet objects in ASP.NET 1.x out-of-process sessions and opt for plain arrays of column and row data. In ASP.NET 2.0, set the new RemotingFormat property before you store it.

Storing Session Data

When working in StateServer mode, the entire content of the HttpSessionState object is serialized to an external application a Microsoft Windows NT service named aspnet_state.exe. The service is called to serialize the session state when the request completes. The service internally stores each session state as an array of bytes. When a new request begins processing, the array corresponding to the given session ID is copied into a memory stream and then deserialized into an internal session-state item object. This object really represents the contents of the whole session. The HttpSessionState object that pages actually work with is only its application interface.

As mentioned, nonbasic types are serialized and deserialized using the system's binary formatter class, which can handle only classes explicitly marked to be serializable. This means that COM objects, either programmatically created or declared as static objects with a session scope in global.asax, can't be used with an out-of-process state provider. The same limitation applies to any nonserializable object.

Configuring the StateServer Provider

Using out-of-process storage scenarios, you give the session state a longer life and your application greater robustness. Out-of-process session-state storage basically protects the session against Internet Information Services (IIS) and ASP.NET process failures. By separating the session state from the page itself, you can also much more easily scale an existing application to Web farm and Web garden architectures. In addition, the session state living in an external process eliminates at the root the risk of periodically losing data because of process recycling.

As mentioned, the ASP.NET session-state provider is a Windows NT service named aspnet_state.exe. It normally resides in the installation folder of ASP.NET:

%WINDOWS%\Microsoft.NET\Framework\[version] 

As usual, notice that the final directory depends on the .NET Framework version you're actually running. Before using the state server, you should make sure that the service is up and running on the local or remote machine used as the session store. The state service is a constituent part of ASP.NET and gets installed along with it, so you have no additional setup application to run.

By default, the state service is stopped and requires a manual start. You can change its configuration through the property dialog box of the service, as shown in Figure 13-5.


Figure 13-5: The property dialog box of the ASP.NET state server.

An ASP.NET application needs to specify the TCP/IP address of the machine hosting the session-state service. The following listing shows the changes that need to be made to the web.config file to enable the remote session state:

<configuration>     <system.web>         <sessionState             mode="StateServer"             stateConnectionString="tcpip=MyMachine:42424" />     </system.web> </configuration> 

Note that the value assigned to the mode attribute is case sensitive. The format of the stateConnectionString attribute is shown in the following line of code. The default machine address is 127.0.0.1, while the port is 42424.

stateConnectionString="tcpip=server:port" 

The server name can be either an IP address or a machine name. In this case, though, non-ASCII characters in the name are not supported. Finally, the port number is mandatory and cannot be omitted.

Important 

The state server doesn't oppose any authentication barrier to requestors, meaning that anyone who can get access to the network is potentially free to access sessions data. To protect session state and make sure that it is only accessed by the Web server machine, you can use a firewall or IPSec policies. Another security-related countermeasure consists of changing the default port number. To change the port, you edit the Port entry under the registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters. Writing the port in the web.config file isn't enough.

The ASP.NET application attempts to connect to the session-state server immediately after loading. The aspnet_state service must be up and running; otherwise, an HTTP exception is thrown. By default, the service is not configured to start automatically. The state service uses .NET Remoting to move data back and forth.

Note 

The ASP.NET state provider runs under the ASP.NET account. The account, though, can be configured and changed at will using the Service Control Manager interface. The state service is slim and simple and does not implement any special features. It is limited to holding data and listens to the specified port for requests to serve. In particular, the service isn't clusteraware (that is, it doesn't provide a failover monitor to be error tolerant) and can't be used in a clustered world when another server takes on the one that fails. Finally, note that by default the state server only listens to local connections. If the state server and Web server live on different machines, you need to enable remote connections. You do this through another entry in the same registry key as listed above. The entry is AllowRemoteConnection and must be set to a nonzero value.

Persist Session Data to SQL Server

Maintaining the session state in an external process certainly makes the whole ASP.NET application more stable. Whatever happens to the worker process, the session state is still there, ready for further use. If the service is paused, the data is preserved and automatically retrieved when the service resumes. Unfortunately, if the state provider service is stopped or if a failure occurs, the data is lost. If robustness is key for your application, drop the StateServer mode in favor of SQLServer.

Performance and Robustness

When ASP.NET works in SQLServer mode, the session data is stored in a made-to-measure database table. As a result, the session data survives even if SQL Server crashes, but you have to add higher overhead to the bill. SQLServer mode allows you to store data on any connected machine, as long as the machine runs SQL Server 7.0 or newer. Besides the different medium, the storage mechanism is nearly identical to that described for remote servers. In particular, the serialization and deserialization algorithm is the same, only it's a bit slower because of the characteristics of storage. When storing data of basic types, the time required to set up the page's Session object is normally at least 25 percent longer than in an InProc scenario. Also in regard to this issue, the more complex the types you use, the more time will probably be required to manage the session data.

Note 

When you have to make a decision between state server or SQL server storage, consider the fact that SQL Server is cluster-aware, which makes a solution based on it more robust and reliable than one based on a state server.

Configuring Session State for SQL Server Support

To use SQL Server as the state provider, enter the following changes in the <sessionState> section of the web.config file:

<configuration>   <system.web>     <sessionState        mode="SQLServer"        sqlConnectionString="server=127.0.0.1;integrated security=SSPI;" />   </system.web> </configuration> 

In particular, you need to set the mode attribute (which is case sensitive) to SQLServer and specify the connection string through the sqlConnectionString attribute. Notice that the sqlConnectionString attribute string must include a user ID, password, and server name. It cannot, however, contain tokens such as Database and Initial Catalog, unless (and only in ASP.NET 2.0) a custom database is enabled, as mentioned in Table 13-8. You can specify a SQL Server Initial Catalog database name or use the SQL Server Express attachDBFileName to point to an MDB file in the connection string only if the allowCustomSqlDatabase configuration setting is enabled. If that setting is disabled, any attempts to specify these settings in the connection string will result in an exception.

Note 

In ASP.NET 2.0, the connection string for an out-of-process session-state implementation (both SQLServer and StateServer) can also be specified referring to a connection string defined in the <connectionStrings> section. The session-state module will first attempt to look up a connection string from the <connectionStrings> section with the name specified in the appropriate <sessionState> attribute; if it is not found, the session state will attempt to use the specified string directly.

As for credentials to access the database, you can either use User ID and passwords or resort to integrated security.

Note 

Whatever account you use to access session state in SQL Server, make sure that it is granted the db_datareader and db_datawriter permissions at the very least. Note also that to configure the SQL Server environment for storing session state, administrative privileges are required, as a new database and stored procedures need to be created.

In ASP.NET 2.0, session state in SQL Server mode now supports the specification of a custom command timeout value (in seconds) to accommodate slow-responding-server scenarios. You control this value through the sqlCommandTimeout attribute, as mentioned in Table 13-8.

Creating the SQL Server Data Store

ASP.NET provides two pairs of scripts to configure the database environment by creating any needed tables, stored procedures, triggers, and jobs. The scripts in the first pair are named InstallSqlState.sql and UninstallSqlState.sql. They create a database called ASPState and several stored procedures. The data, though, is stored in a couple tables belonging to the TempDB database. In SQL Server, the TempDB database provides a storage area for temporary tables, temporary stored procedures, and other temporary working storage needs. This means that the session data is lost if the SQL Server machine is restarted.

The second pair consists of the scripts InstallPersistSqlState.sql and UninstallPersistSqlState.sql. Also in this case, an ASPState database is created but the tables are persistent because they are created within the same database. All scripts are located in the following path:

%SystemRoot%\Microsoft.NET\Framework\[version] 
Important 

In ASP.NET 2.0, these script files are included for backward compatibility only. You should use aspnet_regsql.exe to install and uninstall a SQL session state. Among other things, the newest aspnet_regsql.exe supports more options, such as using a custom database table. In ASP.NET 1.x, you still have a version of aspnet_regsql but with some limitations there are no persistent tables and no custom tables.

The tables that get created are named ASPStateTempApplications and ASPStateTempSessions. Figure 13-6 shows a view of the session database in SQL Server.

image from book
Figure 13-6: The ASPState database in SQL Server 2000.

The ASPStateTempApplications table defines a record for each currently running ASP.NET application. The table columns are listed in Table 13-9.

Table 13-9: The ASPStateTempApplications Table

Column

Type

Description

AppId

Int

Indexed field. It represents a sort of auto-generated ID that identifies a running application using the SQLServer session mode.

AppName

char(280)

Indicates the application ID of the AppDomain running the application. It matches the contents of the AppDomainAppId property on the HttpRuntime object.

The ASPStateTempSessions table stores the actual session data. The table contains one row for each active session. The structure of the table is outlined in Table 13-10.

Table 13-10: The ASPStateTempSessions Table

Column

Type

Description

SessionId

char(88)

Indexed field. It represents the session ID.

Created

DateTime

Indicates the time at which the session was created. It defaults to the current date.

Expires

DateTime

Indicates the time at which the session will expire. This value is normally the time at which the session state was created plus the number of minutes specified in Timeout. Notice that Created refers to the time at which the session started, whereas Expires adds minutes to the time in which the first item is added to the session state.

LockDate

DateTime

Indicates the time in which the session was locked to add the last item. The value is expressed as the current Universal Time Coordinate (UTC).

LockDateLocal

DateTime

Like the previous item (LockDate), except that this one expresses the system's local time. Not available in ASP.NET 1.x.

LockCookie

int

Indicates the number of times the session was locked that is, the number of accesses.

Timeout

int

Indicates the timeout of the session in minutes.

Locked

bit

Indicates whether the session is currently locked.

SessionItemShort

VarBinary(7000)

Nullable field. It represents the values in the specified session. The layout of the bytes is identical to the layout discussed for StateServer providers. If more than 7000 bytes are needed to serialize the dictionary, the SessionItemLong field is used instead.

SessionItemLong

Image

Nullable field, represents the serialized version of asession longer than 7000 bytes.

Flags

Int

Indicates action flags initialize item or none from theSessionStateActions enum. Not available in ASP.NET 1.x.

The column SessionItemLong contains a long binary block of data. Although the user always works with image data as if it were a single, long sequence of bytes, the data is not stored in that format. The data is stored in a collection of 8-KB pages that aren't necessarily located next to each other.

When installing the SQL Server support for sessions, a job is also created to delete expired sessions from the session-state database. The job, which is shown in Figure 13-7, is named ASPState_Job_DeleteExpiredSessions, and the default configuration makes it run every minute. You should note that the SQLServerAgent service needs to be running for this to work.

image from book
Figure 13-7: The SQL Server job to delete expired sessions.

Reverting to the Hosting Identity

In ASP.NET 1.x, credentials used to access the SQL Server stored session state depend on the connection string. If explicitly provided, the user name and password will be used to access the database. Otherwise, if integrated security is requested, the account of the currently logged-in client is used. This approach clashes with the StateServer state provider, which uses the ASP.NET identity to do its job. More important, though, it poses some administrative issues for intranet sites using client impersonation. In these cases, in fact, you have to grant access to the database to every client account that might be making calls.

In ASP.NET 2.0, the useHostingIdentity attribute (shown in Table 13-8) lets you decide the identity to be effectively used. Breaking the ASP.NET 1.x behavior, in ASP.NET 2.0 when the SQLServer state provider is used with integrated security the identity is that impersonated by ASP.NET. It will typically be ASPNET or NETWORK SERVICE or any other account impersonated by the ASP.NET worker process through the <identity> section of the configuration file. This simplifies the administrative experience for intranet sites, requiring that only the ASP.NET account is granted access to protected and critical resources. The useHostingIdentity attribute defaults to true, which enables you to revert to the ASP.NET identity before making calls to the SQLServer session-state provider. This will also happen if a custom provider is used.

Note 

If you're using Windows integrated authentication to access SQL Server, reverting to the host identity is the most highly recommended option for security reasons. Otherwise, it is advisable that you create a specific account and grant it only rights to execute session-state stored procedures and access related resources.

image from book
Session State in a Web Farm Scenario

ASP.NET applications designed to run in a Web farm or Web garden hardware configuration cannot implement an in-process session state. The InProc mode won't work on a Web farm because a distinct worker process will be running on each connected machine, with each process maintaining its own session state. It doesn't even work on a Web garden because multiple worker processes will be running on the same machine.

Keeping all states separate from worker processes allows you to partition an application across multiple worker processes even when they're running on multiple computers. In both Web farm and Web garden scenarios, there can be only one StateServer or SQLServer process to provide session-state management.

If you're running a Web farm, make sure you have the same <machineKey> in all of your Web servers. (More details can be found in Knowledge Base article Q313091.) In addition, for the session state to be maintained across different servers in the Web farm, all applications should have the same application path stored in the IIS metabase. This value is set as the AppDomain application ID and identifies a running application in the ASP.NET state database. (See Knowledge Base article Q325056 for more details.)

In ASP.NET 2.0, partition resolvers are also introduced to let a session-state provider partition its data onto multiple back-end nodes. This allows you to scale session state on large Web farms, according to a custom, user-defined load-balancing scheme. A partition provider is a component that supplies the connection string (the actual string, not the pointer to a string in the web.config file) to the session state that is used to access data, overriding any other settings in the <sessionState> section.

 


Programming Microsoft ASP. Net 2.0 Core Reference
Programming Microsoft ASP.NET 2.0 Core Reference
ISBN: 0735621764
EAN: 2147483647
Year: 2004
Pages: 112
Authors: Dino Esposito
BUY ON AMAZON

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net