Web Sessions

Summary

I’m going to create a series about how Microsoft handles sessions for VB.Net and C# web applications. The purpose of these posts will be to provide a clearing-house of all the information needed to get a common session system going between multiple languages.

The Problem

Web sites typically use session data to keep track of who is logged in and what state they are in. I’m not going to go into details on why sessions are used or how to use them to build a website. Instead, I’m going to assume you are already familiar with this technique and you’re saddled with a large amount of legacy code that cannot be converted in one shot. Let’s say you have a website in PHP and you’re attempting to migrate into a C# environment. How do you go from one web page in PHP running on a Unix server into a C# program running on an IIS server?

There are many solutions, such as cookies, tokens passed in the URL, a GUID stored in a hidden field, etc. The smoothest solution would be to somehow share the session data between different languages so that one page at a time can be converted and the URL from the old page can be redirected to the new page with a smooth and secure transition. The first thing to recognize is that we’re going to have to store the session data in a database that is shared by all web sites that will be connected into one web application. Microsoft provides this capability through their own session management.

Using MS SQL Server to Store Session Data

For Dot Net applications, you can setup a SQL server to store the session data. The following link is probably your best article for getting SQL setup with the ASPState database and redirecting your application to point to the new database:

Configuring ASP session state on SQL server

Once you have set this up, you’ll need to make sure your user rights are setup in the ASPState and the tempdb database. The session data is actually stored in the tempdb database in two tables: ASPStateTempApplications and ASPStateTempSessions. The ASPStateTempApplications table contains the name of the application and the unique app id used by the session cookie (I’m going to assume you’re using the cookie mode in iis, since it is the default). The ASPStateTempSessions table contains one record per session created. All of the session data is encoded and stored in a binary field in this table called SessionItemShort (or if it’s larger than 7k, then it’ll be in SessionItemLong which is an image data type).

The Session Cookie

When your application creates a session, a cookie is created with the application id and a unique session id. The default cookie name is “ASP.NET_SessionId”. If you look at the session id the tempdb.ASPStateTempSessions table, you’ll discover that it is a large alphanumeric string. That string represents two parts: The session GUID and the application ID. The application ID is in hex in the ASPStateTempSessions table and it is in decimal in the ASPStateTempApplication.appid field. If you are going to read the session data from the tempdb database ASPStateTempSessions table, then you’ll need to add the application ID to the end the cookie value. Take your application name and read the application id from the ASPStateTempApplications table. Convert this to hex, then append to the cookie value. This will be the primary key of the ASPStateTempSessions table for your session data.

If your googling skills are savvy enough, you will have discovered most of this information from this article: Session State Providers.  

The next thing to note about this session setup is that the cookie is a non-persistent cookie. There is no expire date and this type of cookie will remain until you close your browser.

If you dig into your SQL server and you look at your SQL Server Agent jobs, you’ll see a new one called ASPState_Job_DeleteExpiredSessions. This job will execute the stored procedure: DeleteExpiredSessions once per minute. The sole purpose of this stored procedure is to delete all cookies where the expires field is beyond the current date/time. This will cause the session to expire. If you look at this date/time in the
ASPStateTempSessions table, then refresh your browser, you’ll notice that the time updates. The time will always be 20 minutes into the future (if your session is set to expire in 20 minutes, which is the default). If your web page goes idle for more than 20 minutes, then you’re toast.

Sharing Session Data Between VB.Net and C#

The easy method of sharing between two languages is to set the application name to the same name in the global.asax file for both programs:

Session State shares session across subdomain, VB.NET website C# MVC 4 Application

Session Data

The session data that is stored in the tempdb.ASPStateTempSessions table is an encoded version of all the session variables and data used by your program. There is this code in C#, which can decode this data into a list of variables:

christian-blades-cb/ASPSessionDecoder

This code does not handle objects, but it does demonstrate the complexity of how this is encoded. Creating an encoder and decoder for this data for a multitude of languages would be very handy. Especially if you wanted to use many languages in one large monolithic application. I believe the reason that Microsoft encoded this data into one large field instead of using a sub-table of fields and data, is that they can store the session data for each session in one record. This prevents a lot of table locking issues with deleting records and it also reduces the amount of time it takes to read and write to the database (assuming they had a database in mind when they designed this system. If you look closely at the DeleteExpiredSessions stored procedure inside the ASPState database, you’ll see that a query of all the expired sessions is put into a temp table. Then the temp table is looped through and each session record is re-checked as it is deleted, just in case it was updated or deleted while this operation was in progress.

Wrap up

For this blog post, that’s all I’m going to go into. Armed with this information anybody can make a decision on how they want to pursue sessions with legacy code and new code. For instance, you could design your own session system to mimic what Microsoft does and use child records to store your variables. I am unsure how this will perform or what issues you’ll run into with this method. You could write encoders and decoders for the session data and use the data that Microsoft stores (avoiding the need for converters and decoders from VB.Net and C# (i.e. you could write a codec for PHP, Classic ASP, Java). By storing your session in the database, you can use different IIS applications for each language (or divide your systems into multiple applications). You can also prevent your session from clearing when an IIS server is re-cycled, or if you have a server farm, you don’t need to worry about which server the web request returns to.

Leave a Reply