Type Safe Session Variables

H02C0001 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:

  1. 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
  2. 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; 
         }
    }
}

Like this Article? Subscribe to get every article sent to your email.

Related Post

  • Self Executing Anonymous FunctionSelf Executing Anonymous Function Not because it is all that new, but because it took me a while to find it, here’s how to create a self executing anonymous function using CSharp, just like you can do in JavaScript. […]
  • CSharp VAR MisconceptionsCSharp VAR Misconceptions I find it amazing that .NET 3.5 has been out for over a year and people still don’t understand the “var” keyword. Just last week I got a comment on one of my videos asking why I used […]
  • ASP.NET Session Variables Not StickingASP.NET Session Variables Not Sticking I’ve stumbled across this problem twice in the last couple of months so I figure it is about time I blogged about it. The situation is that you have  a page on your web site that […]
  • ASP.NET Assigning a Role to a UserASP.NET Assigning a Role to a User Another function that is not supplied by one of the existing controls in ASP.NET is the ability to assign a user to a role.  For this, we will need to resort to using the APIs. […]
  • ASP.NET Substitution ControlASP.NET Substitution Control Tucked away on the toolbar is a little-used and often overlooked control.  Not using this control could be costing you in performance. The control I’m referring to is the […]

About Dave Bush

Dave Bush is a .NET programmer and Certified ScrumMaster who is passionate about managing risk as it relates to developing software. When he is not writing or speaking about topics related to Application Lifecycle Risk Management (ALRM), he is an example to his peers as he develops web sites in the ASP.NET environment using industry best practices.

  • http://blog.reamped.net/ Ira

    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 

    }

  • http://jclaes.blogspot.com Jef Claes

    I have been doing this for some time now.

    Good thing you blogged about it!

  • http://www.sholo.net/ Scott Holodak

    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.

    • Dave

      Personally, I’d rather get the error and find out quickly that the session was misused.

  • http://donnyvblog.blogspot.com Donny V

    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;
    }
    }

Awards & Certs


Links