Session and Cookies in ASP.NET MVC? Oh my!


This post is brought to you by this post on LinkedIn (you may need to belong to the ASP.NET MVC group). The question of the day:

In MVC it bad practice to use session & cookies then what are the options to maintain session

If you understand how HTTP works, you understand this is a bad question, or at least one born out of ignorance.

Before getting into the meat, let’s examine two important concepts: synchronicity and state.

Synchronicity is whether or not we immediately get feedback. For example, if I fill out a form to join and immediately get logged on, it is a synchronous system. If, instead, I fill out the form and get a email with a link and then log in, it is asynchronous. A better example is a chat application (synchronous) versus email (asynchronous) or the difference between the chat window in Facebook (synchronous) versus either sending a Facebook message, playing words with friends or using Twitter (asynchronous).

Now to state. State is the current “data” stored about you, or something else, in the system. Oversimplification, but consider I have $1000 in the bank. The state of my account is $1000 on the positive side. If I then get $100 cash, the state is $900 in the bank. The same is true if I change my Facebook status to single (not my real status, of course, but it would be my state in the system).

How applications work (and some history)

The first applications were normally either dumb terminals (maximum statefulness and synchronicity) or client/server applications (high level of statefulness and synchronicity). When you logged in, you were connected full time to the server, so any changes were instantly reflected. Not 100% true, but it covers the general nature.

Now, let’s move up to the web. The client is not connected to the server except when making a request, making it an asynchronous and stateless system. This may take a moment to sink in, but I feel the need to disgress (ADHD popping up?) and cover how we got here.

I first got on the Internet in the late 80s through shell programs on a BBS (bulletin board system). At this point in time, you had email and newsgroups as your primary means of communication with other people. To organize information, you had Gopher. Gopher was a decent system for putting “books” on the Internet, but a bad system for user interaction.

One more step into ADHD land? :: The government (and education) started what would become the “Internet” in the late 1960s as ARPANET. They brought education in, and ultimately other countries (our allies), in the 1970s.

Now, let’s cover the WWW. Gopher was a bit of a pain to program with. But that changed when Tim Bernas-Lee took a government standard (SGML, or Standard Generalized Markup Language) and created HTML (HyperText Markup Language). The main push was to make it easier to disseminate information, but it was easy enough to create applications that were interactive. I could go deeper (will consider in another post) and get into what HyperText truly means (perhaps a post on REST?).

Now, you have a bit of background, let’s get to the core. Hypertext applications are both stateless and asynchronous. The operations in these types of applications may be synchronous (added to avoid arguments from purists), but the basic nature of the communication is asynchronous, as you

Hypertext applications work on a request and response system. You create a request and send it to the server. Prior to your request coming in, the server has no clue who you are, even if you have contacted it 20 times in the last 2 minutes. Every request is treated as a new request from an unknown entity, making it stateless. The server disconnects after the response is sent, so it is non-connected (except to handle requests) and you can take time to determine the next course of action, making it asynchronous.

Now some may argue with the last line of the last paragraph, thinking “if I am logged in, I can’t walk away for a long time; I have to fill in the form within X minutes or I have to start over”. This is true, but as long as you have some means of saving state to the server, you can pick up with the remainder of your work at any time. And, if you are not logged in, you can keep the page open, shut down your computer, and come back and click links on the page hours, or even days, later. So the basic nature of hypertext is stateless. That is our important takeaway to move to session and cookies.

Persistence

Persistence is the mechanism by which state is stored until a user is ready to use it again. Long term persistence is usually handled either by a database or files. Once the user has changed something, the information is normally persisted to these long term persistent stores.

In addition to long term persistence, there is short term persistence. This is where cache comes in. Cache is persisting of state in memory. What about session? Session is a cache that includes bits to tie information to a particular user. Session also allows for expiration of cached state based on a user logging out (immediate) or timing out (end of session time). When either condition is met (log out or time out), the user specific state is cleared.

It should be noted that the main difference between a database, files, memory cache and session is where the state is stored. This is important for reliability and speed. Storing in memory fails if the machine is rebooted (or worse, the power pulled), but it is much faster to retrieve from memory than involve I/O (either pulling from disk, over the network or both).

Then what are cookies? Cookies are another form of persistence mechanism, only the information is stored on the client. The cookie may simply persist a user ID (to retrieve from session) or it may persist all of the user’s data (impractical over a certain amount of information). If it is just an ID, you need another method to pull the rest of the information, which means persistence on the server.

In Summary, for this section of this post (there are others, just not relevant):

Server Side Persistence

Database

Files (XML or otherwise)

Cache (temporary)

Session (temporary)

Client Side Persistence

Cookies

Kludges, aka sessions and cookies

This may seem unfair calling these items kludges, but let’s examine. You have a stateless mechanism (web pages), as they do not hold state. The client is only connected for the length of a request and either errors or fulfills the request and then shuts it down. The request is forgotten after the response is sent.

But, you need state. So you first create a means of storing information on the client. This is the cookie. Think of a cookie as a property bag storing name/value pairs. This is sent to the client as part of the header of the response (ie, the part you don’t see in your browser). The client then stores it and sends it back with every request to this server.

But what happens if you need more information than can be stored in a cookie. Then you create an in-memory cache tied to the user via some type of session ID. If you have been paying attention, you realize the session ID is sent to the user with every request and sent back in.

But, what if people find out cookies can be used for things they don’t like and turn them off? This was an early problem with the web (mid 90s). Browser developers put the ability to refuse cookies (the cookie is still sent, but it is not stored, so it will not be sent with the next request). To solve this, another cookie store was created on the client side and they called these “server cookies”. When the user decided to turn off cookies, these cookies stay alive, as they are in a different store.

The store for server cookies was designed to purge when the user left the site, but since the developer on the server side has some control, this did not always happen. The end result is while it is harder to turn off server cookies in all browsers, it is not impossible.

Are Session and Cookies bad in ASP.NET MVC?

If you have read this far, it should be obvious that session and cookies are simply a persistence mechanism between stateless requests. Are they bad? Yes and no. In many cases, cookies and session are a crutch to cover up bad architecture and design. In those cases, I would say they are bad. Overall, I would question the use of session and cookies in ASP.NET MVC, especially if you don’t truly understand the nature of Hypertext communication (and no, this session is not the 101 class).

On the original post, Ignat Andrei posted “And if it is a problem – it’s not only a MVC problem – it’s an ASP.NET problem.”. Correct, it is a problem in ASP.NET, as well. Or at least a variation of the same kludgy solution. In fact, it is a “problem” in all HTTP centered apps that allow for session (web server controlled in-memory cache) and cookies.

One of the beauties of ASP.NET MVC is you can get rid of a false reliance on the Session object and/or cookies for most of your work. Not that MVC is really that different from any other web application (it is just a pattern), but that the pattern should get you thinking in paradigms where you don’t rely on kludgy state mechanisms.

ASP.NET MVC was created due to a couple of reasons. The most obvious is Ruby on Rails, since Rails uses the MVC pattern. But another concern is pushing people towards a paradigm that encourages use of best practices, primarily separation of concerns. While the paradigm works fairly well, in many cases, you don’t solve process and people problems with technology, at least not completely.

Now back to the question of bad for session. Why would it be bad? One reason is users generally use session as a crutch to store page items. This is overcoming bad architecture with bad practices.

Another reason is session takes up space on the server. You don’t get session for free. When you use session, you take up memory and reduce scale. This is not always bad, but you do have to be aware of it. The question comes down whether scalability is an issue. The same is true of any form of in-memory cache, but you can easily switch to a distributed cache if you are using MemoryCache, by using a factory or provider pattern; you don’t have the easy configuration change type of switch going from Session to distributed (at least not without adapters) and even if you could, the purpose and pattern are different.

Another reason is IIS recycles. Not often that it screws over most of your users, but it does. Since HTTP is stateless, the user can still request pages, but now he is hosed as far as anything stuck in session goes. The same can be true of having to log back in, depending on your mechanisms, however.

Another reason is web farms. Not a big deal for the single server “share my club” type of site, but if you have a site on multiple servers, you end up with session in memory on all of the servers (at least the potential of that). ouch!

Now the comeback is “Greg, I use session state in SQL Server”. Great! Then why use session at all? If you are taking the trip to SQL Server for every hit, why incur the consumption of extra space for items that may never be requested. And why incur the extra overhead of clearing a user’s session, including the piece where you clear the data out of SQL Server. It is pure overhead at this point.

Does this mean never use session? Let’s look at that in a section entitled …

What if I feel the need to use Session in ASP.NET MVC

Did you not read the rest of this post? Okay, so there is an alternative: Use TempData instead. It is an abstraction in ASP.NET MVC on top of the old ASP.NET session. And it allows you to more easily change types of persistence. Realize this is still an abstraction on top of a kludge, but it is a useful abstraction as it is easily switched to a better method.

But you did not answer if it was bad …

As with everything in life, there is no one size fits all answer. As an example, I present adriamycin. Originally developed as an antibiotic, it was found to be too toxic. But it is rather effective on certain types of cancer, so while it is a poison, and should generally not be consumed, there are times it is the most effective path.

Read that again. What I am saying is I would generally avoid session like the plague, but there are always exceptions.

If you want a rule of thumb: Avoid the use of session to store temporary values, unless you can find no other mechanism, or the factors of developing the application make session a better option. The same can be said of storing in cookies.

The Aspects of Development and Session

All of this stems back to the aspects of development. There are five major aspects to consider:

  • Availability
  • Scalability
  • Maintainability
  • Performance
  • Security
  • In addition to these, time and budget have to be considered, as they are valid concerns. If using session is needed for time, for example, you may have to code it that way. But make sure there is time to remove it later if you find you are using it in a kludgy manner. The same is true of budget, but then time is money.

To figure what is best, you look at each application uniquely and determine the best mix of the aspects. If scalability is the biggest issue, you may lose some performance to better separate out concerns (monoliths run fast, but scale horribly). In financial applications, security is often the biggest concern. In general, maintainability (or the lack thereof) cost more money than any other aspect.

Summary

Session (and cookies) are often used as persistent mechanisms of convenience. They were both built as kludges to make a stateless system stateful. As such, unless you have a proper reason for using them, you should not use them. And, if you have a proper reason, you should examine it and see the proper reason is based more on familiarity than true need.

But, the above advice should be said for every architecture/design you have. You should examine all of your assumptions and ensure you have made proper decisions. Only then can you be sure things are solid (nice play on words, eh?)

Realize that the above has a caveat. You have to be able to examine within the time constraints of the project. If you can’t deliver, it does not matter how good the product is.

For your club website, session, while not the best solution, is probably fine. The same is true for the use of cookies. Once you move into the Enterprise space, however, these kludges can become costly.

Peace and Grace,
Greg

Twitter: @gbworld

Advertisements

18 Responses to Session and Cookies in ASP.NET MVC? Oh my!

  1. I am regular reader, how are you everybody?
    This piece of writing posted at this website is in fact good.

  2. Ali says:

    I have read this and agree with not using sessions as a way of storing basic info. The issue I am trying to get around without using Sessions/TempData is the one of the following simple example.

    User fills out a form and you redirect to another view and that view contains a “thank you/form saved message” I know you can use querystrings but without session or tempdata what would be good design practice. Again, knowing that this can be achieved with Ajax but would prefer to do with the PRG pattern of MVC.

    Great article.

  3. Lelala says:

    Sorry, i just don’t get it:
    Lets say you are handling the question “is-user-logged-in?” by setting a session object to Session[“LogOn”]=true – what’s wrong with that? And: doing a tript to the SQL database just to get this info-flag? Mmh… i’m note sure if that is really a faster & better way?

    • A couple of notes. First, there is a trip whether it is to a persisted store (database), a cache or too session. Session, unfortunately, has many pitfalls, especially if you use a web farm (but that is beyond this comment). Regardless of where you store information, you have to retrieve it. Second, if you are merely determining whether a user is logged in, there are currently many ways to do that outside of setting a session flag. Third, as the article states, there is more to a web application than speed. In fact, if you think about it, many items that are pure performance focused are technically bad for scaling solutions, as scale requires putting items across multiple servers unless you are limiting to vertical scale only. I will have to re-read the post to figure out the specifics you are talking about.

      • razor56Boyle says:

        “there are currently many ways to do that outside of setting a session flag.”
        Could you please explain one of the ways and prove that is better then setting a session flag?

      • zrrtcs says:

        ASP.NET MVC gets their design inspirations from Rails. Coming from a Rails background and starting to learn ASP.NET MVC makes me confused about session. Could you tell us what you meant by “there are currently many ways to do that outside of setting a session flag”. I almost never heard of storing such information in sessions bad in the Rails community. This is the advice regarding session in Rails official guide: “http://guides.rubyonrails.org/security.html#session-guidelines”

        Thanks.

      • The session object is more of what I am talking about. And it is not necessarily bad, but you should be aware of the consequences of using it as a crutch. And you can see some of the same advice in the Rails guide, where it warns about large objects and not putting critical objects in session, as the user can erase them.

      • Matt Carr says:

        One of the alternatives of using session to see if user is logged in is to use HttpContext.Current.User.IsAuthenticated or some other property like that. When a user logs into your web application, by default, this information is stored into a security cookie.

  4. Juwel Ahmed says:

    Good Article

  5. Roman says:

    So, how do you handle a concept of logged in user without cookies/session? Imagine you have a banking application and retrieving person’s accounts/transactions/etc is a very expensive task (because you don’t own them, obviously, they sit in a whole other core system). How would you, as a user like the lack of persistence between requests? Because each request is brand new, the application would need to reauthenticate the user on every request and refetch their data. Would be a very sluggish system.

    • Roman: The “session is bad” allusion is aimed more at the use of the session object than the concept of maintaining state in a stateless environment. You have to have some type of “kludge” to maintain a user after a log in. I never stated one should not maintain the concept of a single log on per session. I was focused on the even more awkward session object.

  6. Vizion says:

    I understand your article, but have a hard time understanding how you’d implement a shopping cart without a session?

      • AiApaec says:

        Do you mean “SessionState = SqlServer”? or avoid Session definitively? if this last question is yes then I imagine the solution:
        When user is LoggedIn(he put correct data): we must set a column in database (“IsLoggedIn=true”).
        After LogIn: In every Post, before to do some operation like update a record we must verify if “IsLoggedIn=true”, if true we can update the record.

        When user Log Out: we must set a column in database (“IsLoggedIn=false”).

        But this way “session”(our implementation) never change, I mean “IsLoggedIn=true” never change even if Asp.Net’s Session dead, if a user is logged-in and the go out and come back after 8 hours he can do operation still(“IsLoggedIn=true”).
        A solution may be to setup Session’s timeout to X minutes and to put an ajax function in every page and execute it every (X-1) minutes, the ajax function first would show a message “In one minute your session will expire, please press ‘i’m workin to refresh session’ (this is a button) or your will be log out”, if user press button ‘i’m working’ then ajax will send to the server “Working=true”, if not ajax will send “Workin=false”, in the controller we must verify:
        if “Working=false” then change value in database (“IsLoggedIn=false”).

        Well, I’m a dummy, maybe that was a crazy ang worng idea.I hope you answer my question.Please.Thank you.

        PD: Pardon my poor english.

  7. Manjuboyz says:

    I read this article and feels dilemma about using session/cookies and suggested to use TempData, I give my scenario let me know what’s wrong in this, I built and MVC application with login information, that Login name should be carried to another page(view), but I used both session and TempData, it works fine, but if the application is idle for few mins like 5, then the variable will be nulll!, it erases the data on session as well as tempdata, but if I used Cookies, it stays there until application quits, so anybody there what is wrong and which is wrong ??

  8. Bubba Hyde says:

    Author tells us what is bad, but doesn’t offer alternatives. Not very helpful.

    • Dave Lopez says:

      Bubba, I completely agree. The entire article I was waiting for him to offer alternatives and he just punted on the whole issue….very frustrating.

      • David B says:

        Same. If you can’t offer a good alternative, you have no right to criticise something as bad.
        Also the major aspects of development listed don’t cover the most important one… WHY? (as in why are we developing?) which usually comes down to user interaction and user experience and unless you’re big enough to force unusable software on suffering users you will find that persisting data actually matters.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: