Wednesday, September 21, 2011

Strongly typed Session with MVC3 and Spring.NET - Part - 1

In every Web project I have worked so far, always there is a need to store some or the other information in HTTP Session.

I am very finicky about putting things in the HTTP Session.  IMHO HTTP Session should be kept as light as possible.  There should be a very very strong and compelling reason to put a certain value in the HTTP Session.  Having said that, I do agree that there are times when we want to put certain information in the HTTP Session like user name, user id, etc.

With me so far?  Till now we understand that, we do not like to put things in HTTP Session, however, we understand that there is a definite need to put certain things in HTTP Session for the app to work correctly.

Question is, Is there an alternate to putting things in HTTP Session?

In this series of three posts we will try to answer this question.  We will try to use MVC3 and Spring.NET to eliminate the need of putting stuff in HTTP Session.

But wait a minute, let's first answer this question,

Why is putting things in HTTP Session is such a bad idea?  

Lets start by looking at the code that will put UserName into the HTTP Session.
Does it remind you of code that you have seen in one of your applicatoin? It certainly reminds me of code that is used all over the place in one of the projects that I had worked.

I totally hate to see code like this.  Why whats wrong with such code?

Session is used like a Hash Table:

In our example, key of the hash table would be UserName and value will be Git Shah.  Imagine while putting/retrieving values to/from the HTTP Session, if incorrect keys are used, results could be catastrophic.  Even a small typo like one shown in the example below would yield incorrect results
Ofcourse there are ways to get around this problem. Simplest of them is to use a Static Class that holds all the keys as constants.

However, you can still not gaurentee that every programmer on your team will always always use constant keys from the static class.  Believe me, because of human error or some other unexplainable reason, someone would use hardcoded inline key to put value in the Session and rest of the team will curse him/her for eternity! 

Session values are not strongly typed:

We have inserted a string value Git Shah in the HTTP Session against the key UserName but when we want to retrieve the value from the session we will have to typecast to its correct type.  In our example to retrieve the value of UserName key in HTTP Session code would look like
I have a name for code like that, I call it A Time Bomb!

Its just a matter of time before which you start getting a class cast exception.

Dude, whats in my Session? Where are these values used?

Can we say for sure what all values are stored in our session?  

Another important question to answer is, Can we say for sure, from what all places in the code are these values accessed?

These are a very important questions.  Answers to these questions are absolutely vital for the health of your application.

In one of the projects that I had worked, we were extremely confused for a very long period of time.  The question that was bothering us was, who was setting a specific value in the session and in what condition?

Consider an example

UserName key is populated in the LoginController.Login method. Lets look at another place where UserName is used.
AccoutController.UpdateUser updates the value of the UserName key in the HTTP Session to the new value passed as argument and AccountController.GetUserDetails method fetches the value of the UserName key from the HTTP Session and sets the ViewBag.UserName property.

As you can see in our simplistic example UserName key of the HTTP Session is used at three places.  In real life, it would be used in many more places than this.  The code that accesses the UserName key from the HTTP Session would be littered all over the place!

How will we find the exact places where UserName key is populated/fetched into/from the HTTP Session?

There is no easy way to find the exact places where UserName key of the HTTP Session is used.  We can extract a constant for the UserName and then search for its usages, but still this is not a full proof way, as I mentioned earlier, there are many fools out there who will not bother to use the constant and use an Hardcoded string key instead.

These are few of the problems that are a big concern to me.  Question to be answered is,
  • How can we avoid such code?  
  • How can we achieve an alternate option that will discourage people from writing such code?
Before we dig deeper into the solution, lets first focus on some of the design goals that this new solution should have.
  • Things that we put into and fetch from the session should be strongly typed objects.  There should not be any cast of any sort.  This will avoid Time Bomb like code.
  • Session should not be used as a Hash Table.  Whatever we put into the session should become a property of the session which can be accessed from anywhere in the code.  Moreover, because it becomes a property of the HTTP Session, we would get all sorts of intelli-sense on it.  There is no chance of any typo in this case.  For e.g. the existing code
Should no longer be required instead we should have code that looks like
  • At any point in time, it should be easy enough to find the exact places where a certain property of HTTP Session is used. In some ways this point is related to the previous point. If we are able to convert Keys of session into strongly typed Properties then we can just search for the usages of those properties and we know exactly where those properties were used!
Enough goals to start with.  Question is, Can these goals be implemented in real life? 

Well, the good news is, these goals are definitely implementable.  In fact its not too difficult to implement these goals when we use Spring.NET with MVC3. 

What is the bad news?  You will have to wait for my next posts to see how exactly we could implement these goals :)

Stay tuned folks in the next couple of posts we are going to have some fun with HTTP Session Management!
Have some Fun!