Type Safe Session Variables
This may be obvious to everyone else on the Internet. Heck, it’s been obvious to me for several years. But I can’t find anyone else writing about this and it makes so much sense that I’m kicking myself for not trying it earlier. So…
The Problem
We’ve all been there. We are coding away and need a session variable. So we create one using code that looks something like:
Session["myVar"] = "hold this for the future";
And then, on some other page in our system, we need to retrieve it:
string localVar = (string)(Session["myVar"]);
There are two problems with this:
- If I don’t retrieve the variable with exactly the same string, the data will never be there giving me a null pointer in localVar, and
- I have to cast to a string because Session[indexer] always returns an object type.
The first leaves my code prone to unknown bugs and the second is just plain annoying. So I got to wondering, "Is there a way we could wrap all of this up in a class and let the class proxy the Session object? Is it possible to have the Session data stored in a way that is both typed, so we don’t have to cast the data, and allows intellisense to tell us what the name of the item is?
Yep! It sure is.
The Solution
Obviously to get this to work, we are going to need a class; let’s call it SessionData
public class SessionData { }
We do not want this class to be instantiated. We can do this in one of two ways–we could make the class abstract, or we could make the constructor private. Since we only want to make the class so that it cannot be instantiated, it makes more sense to mark the constructor as private.
public class SessionData { private SessionData(){} }
So far, we have a class that does nothing. The next thing we need to do is implement a Session variable as a property. So let’s say we have a session variable named "myVar" that holds a string. We will need a variable to hold the string constant, so let’s create that.
public class SessionData { private const _myVar= "myVar"; private SessionData(){} }
Next we want to implement a property around the session variable. This is where a bit of ASP.NET magic comes in. The session variable is available off of the HttpContext object as well as off of the Page object. And the current context is available off of the static property Current off of the HttpContext class.
To get to the HttpContext class, we will add a using statement at the top of our file:
using System.Web;
And next, we provide the wrapper property.
using System.Web; public class SessionData { private const _myVar = "myVar"; private SessionData(){} static public string MyVar { get { return (string) (HttpContext.Current.Session[_myVar]); } set { HttpContext.Current.Session[_myVar] = value; } } }
The only question remaining is, how do you remove a session variable once you are done with it? With session variables that are pointing to objects, the answer is easy. Assign null to the property.
SessionData.MyVar = null;
But what if MyVar is an integer or some other primitive value? For this, we will need to make the property nullable by adding a ? after the type specifier. So to add a integer property to SessionData, it would look like this:
using System.Web; public class SessionData { private const _myVar = "myVar"; private const _myInt = "myInt"; private SessionData(){} static public string MyVar { get { return (string) (HttpContext.Current.Session[_myVar]); } set { HttpContext.Current.Session[_myVar] = value; } } static public int? MyInt { get { return (int?) (HttpContext.Current.Session[_myInt]); } set { HttpContext.Current.Session[_myInt] = value; } } }
Other Related Items:
Faux Paw's Adventures in the Internet: Keeping Children Safe Online"I encourage all adults to teach children the basic principles of online safety that are found in this book."--First Lady Laura Bush, from the... Read More >
GI Type Combat BootMade by overseas contractor to rigid. US Government specifications. Heavy top grain cowhide leather. Capped toe, ten eyelets.
Rothco G.I. Type Speedlace Jungle BootCondura/suede leather upper, Padded Collar, Removable cushion insole, "Panama" Sole










I have always found it a little easier to type things going in and coming out of the session using a session helper class:
///
/// Helper object for strongly typed access to the session.
///
public class SessionHelper
{
#region Methods (2)
// Public Methods (2)
///
/// Gets the session value.
///
///
/// The key.
/// Returns a
public static T GetSessionValue(string key)
{
T result = default(T);
if (HttpContext.Current.Session[key] != null)
result = (T)HttpContext.Current.Session[key];
return result;
}
///
/// Sets the session value.
///
///
/// The key.
/// The value.
public static void SetSessionValue(string key, T value)
{
if (HttpContext.Current.Session[key] == null)
HttpContext.Current.Session.Add(key, value);
else
HttpContext.Current.Session[key] = value;
}
#endregion Methods
}
I have been doing this for some time now.
Good thing you blogged about it!
Rather than casing the object, consider using the ‘as’ keyword in your get blocks. ‘as’ will return null if the object can’t be cast to the desired type instead of throwing an InvalidCastException. Even though you are providing a class to interface with the Session object in a strongly-typed way, it’s still possible for other developers to short circuit your system and manipulate the Session object directly, so it is possible to get some object type of the Session object that your code doesn’t expect. I think you’d rather get a null value back in that case than an unhandled exception.
Personally, I’d rather get the error and find out quickly that the session was misused.
I’v been doing this for a while now.
One thing I learned in doing this is that in large projects you want
to use a GUID as the session variable. I usually don’t have 1 large session data class. I use it in any class. So you may accidentally use the same session variable. Using the GUID prevents that from happening.
Also you might want to think about some type of rehydration code inside the property. So that when IIS decides to dump the session state in the middle of your code executing it can rehydrate that session from nothing.
Here is an example
string UserAccountSessionID = “88766165-b250-4d65-af10-5f2b6c9eca0d”;
public static UserAccount GetUserAccount
{
get
{
System.Web.SessionState.HttpSessionState SessionState = System.Web.HttpContext.Current.Session;
UserAccount UA = null;
UA = SessionState[UserAccountSessionID] as UserAccount;
if (UA == null)
{
UA = GetUserAccount(CurrentUserID);
SessionState[UserAccountSessionID] = UA;
}
return UA;
}
}