Introduction

Just about every ASP.NET application needs to keep track of data for a user's session. ASP.NET provides the HttpSessionState class to store session-state values. An instance of the HttpSessionState class for each HTTP request is accessible throughout your application using the static HttpContext.Current.Session property. Access to the same instance is made simpler on every Page and UserControl using the Session property of the Page or UserControl.

The HttpSessionState class provides a collection of key/value pairs, where the keys are of type String and the values are of type Object. This means that Session is extremely flexible and you can store just about any type of data in Session.

But (there is always a but) this flexibility does not come without a cost. The cost is the ease with which bugs can be introduced into your application. Many of the bugs that can be introduced will not be found by unit testing, and probably not by any form of structured testing. These bugs often only surface when the application has been deployed to the production environment. When they do surface it is often very difficult, if not impossible, to determine how they occurred and be able to reproduce the bug. This means they are very expensive to fix.

This article presents a strategy to help prevent this type of bug. It uses a Design Pattern called a Facade, in that it wraps the very free interface provided by the HttpSessionState class (that can meet the requirements of any application) with a well designed and controlled interface that is the purpose built for a specific application. If you are not familiar with Design Patterns or the Facade pattern, a quick internet search of "facade design pattern" will provide you with plenty of background. However, you do not have to understand design patterns in order to understand this article.

The example code shown in this article is written in C#, but the concepts are applicable to any .NET language.

What is the Problem?

In this section of the article, I will describe the problems with direct access to the HttpSessionState class, without the facade. I will describe the kinds of bugs that can be introduced.

The following shows the typical code written to access session-state variables.

However, when constants are defined locally (e.g. at page level), we might still re-use the same key unintentionally.

A Better Quick Fix

Rather than define constants on each page, group all session key constants into a single location and provide documentation that will appear in Intellisense. The documentation should clearly indicate what the session variable is used for. For example, define a class just for the session keys:

When you need a new session variable, if you choose a name that has already been used you will know this when you add the constant to the SessionKeys class. You can see how it is currently being used and can determine if you should be using a different key.

However, we are still not ensuring consistency of data type.

A Much Better Way - Using a Facade

Only access the HttpSessionState from within one single static class in your application - the facade. There must be no direct access to the Session property from within code on pages or controls, and no direct access to HttpContext.Current.Session other than from within the facade.

All session variables will be exposed as properties of the facade class.

This has the same advantages as using a single class for all the session keys, plus the following advantages:

Strong typing of what gets put into session variables.

No need for casting in code where session variables are used.

All the benefits of property setters to validate what gets put into session variables (more than just type).

All the benefits of property getters when accessing session variables. For example, initialising a variable the first time it is accessed.

An Example Session Facade Class

Here is an example class to implement the Session facade for an application called MyApplication.

The class demonstrates the use of property getters that can provide default values if a value has not been explicitly stored. For example, the StartDate property provides DateTime.MinValue as a default.

The property getter for the UserAuthorisation property provides a simple cache of the UserAuthorisation class instance, ensuring that the instance in the session variables is kept up to date. This property also shows the use of a private setter, so that the value in the session variable can only be set under the control of facade class.

The Username property demonstrates a value that may once have been stored as a session variable but is no longer stored this way.

The following code shows how a session variable can be accessed through the facade. Note that there is no need to do any casting in this code.

Additional Benefits

An additional benefit of the facade design pattern is that it hides the internal implementation from the rest of the application. Perhaps in the future you may decide to use another mechanism of implementing session-state, other than the built-in ASP.NET HttpSessionState class. You only need to change the internals of the facade - you do not need to change anything else in the rest of the application.

Summary

The use of a facade for HttpSessionState provides a much more robust way to access session variables. This is a very simple technique to implement, but with great benefit.

Comments and Discussions

Some control (i.e. DevExpress ASPxHiddenField allow to set a pair code+value in the server side and then to read it in the client side.
We can use the Façade patter for the server side but then we would have to go back to a string literal for the client side.

Yes, this is a good technique, but I see it could be improved a bit. If someone (like me) wants to follow Dependency Inversion Principle, then direct access to Session or wrapper class violates the principle. Also, by using direct access to real implementation, the code is not Unit Testable.

To achieve this create an interface IApplicationSessionState or similar and use instance where you need it. Setting the instance is easy in MVC (just pass IApplicationSessionState in constructor of your Controller class), but in WebForms it's a bit difficult, but doable. See more details from your IoC container (Autofac, Windsor, etc.).

This is a good practice, but I would add that an interface should be used to get access to those properties. So, the natural implementation will use the real asp.net session, but unit testing could use a completely unrelated implementation.

I just checked the revision history of the article. It was "corrected" by a CodeProject editor back in 2010! I have just submitted an update with one of the "received" changed back to "recieved". The update needs to get approved for publication though, so not sure when it will be visible.

Thanks for the article.
For a larger group of developers (300 +), enforcing the use of a wrapper / facade can be a challnege on its own. Is there any way to restrict the direct access to the HttpContext.Current.Session in the application / .NET solution?

What I have done is periodcally do a check of the code to "find all references" to HttpContext.Current.Session. These should only ever be found in the facade class. It does not take long in Visual Studio to do this. This could possible be automated as a check-in policy.

But I have not bothered as at the same time as checking there are no stray references to HttpContext.Current.Session, I have also taken the time to review the new code that has been added to the facade class.

I tried to use the code as it is for learning purpose. when i tried to compile I got error as "The type or namespace name 'UserAuthorisation' could not be found (are you missing a using directive or an assembly )

could you please let me know from where I should get the UserAuthorization namespace

The code is sample code only and will not compile just by copying the code into your application. You will have the same problem with other things such as ","TeamManagementState" and "MyApplication.Settings.Caching.AuthorisationCache.CacheExpiryMinutes" These classes are application specific examples.

The intention of the article is not to show a real working application but to show a better way of accessing the HttpSessionState for the current user.

The example MyApplicationSession class is used to demonstrate the ideas in the article, such as the class being static, using constants rather than strings when accessing HttpContext.Current.Session, using strongly typed properties, using appropriately scoped property getters and setters, including validation of values in property setters, and providing default initialisation in property getters.

Hi David Hay,
Thanks alot for this knowledge.Can you provided me a demo application (for a example)with this (Manage ASP.NET Session variables using the Facade design pattern) implemented. I want to use this in my application.

i have added one session variable on code behind of one aspx page( Session.Add("strPendingEnquiryQry", strQry);) and trying to access it on asp page( Response.Write "alert('" & Session("strPendingEnquiryQry") & "');" & vbcrlf) but not able to access it .