ASP.Net Quick Tips - State Management

written by Scott Watermasysk on Tuesday, February 27 2007

The web is inheritently stateless, however, ASP.Net provides you with a very comprehensive list of options to overcome this lack of statelessness. Using them effectively is a critical of a successful ASP.Net application.

Tip: Do not use the Application statebag.

Cache does everything you can do with Application. Application was created to smooth the transition of ASP.Old users to ASP.Net. There is no reason to use Application and it should be avoided.

Tip: Use a safe pattern for accessing objects from a statebag.

All statebags take the form of a key/value dictionary. While they are very easy to work with, if you are not careful you can introduce subtle issues and potentially open yourself up to a hard to debug exceptions.

The ideal pattern takes the form of:

MyObject obj = StateBag["key"] as MyObject; if(obj == null) { //Do Something here }

Using this pattern helps to avoid multiple lookups, race conditions, and invalid cast exceptions. The most common abuse of this rule looks like this:

MyObject obj = null; if(StateBag["key"] != null) { obj = (MyObject)StateBag["key"]; }

In the bad example above, we look up the key twice, introduce a possible race condition (what if in-between the key look up and request it is removed), and have a possible invalid cast if the type of object stored by "key" is not of the type "MyObject" (or a derivative/etc).

Tip: Understand the importance of HttpContext.Items.

The HttpContext provides a per request statebag you can use to store objects that are only needed on the current request.  As I have mentioned before it is advisable to avoid Session when possible. However, there are likely objects which are re-used through the course of a request and HttpContext.Items is an idea place for them. The first time I ever heard of the HttpContext.Items was in an article "A Matter of Context" by the great Susan Warren.

Tip: Do not overlook Cookies and Hidden fields.

As I have mentioned a couple times by now, I generally recommend avoiding Session. But there are quite a few times when you need to store values between requests and Cache/Database/etc just do not make sense. Cookies are an excellent candidate to temporary information which needs to exist across multiple pages and hidden fields can be used as a way of quickly tucking away values on a per page basis.

Tip: Know what is in your cookies and ViewState.

Both cookies and viewstate provide excellent ways to store data, but you must always keep in mind that this data will travel to and from the server on every request. Keep it small and simple.

Tip: Do not store secure/secret data in Cookies, Hidden fields, or ViewState.

If you do not want users reading data, tampering with data, etc then do not push it down the client and store it on their machines. This is the equivalent of a putting something shiny and red in front of a baby and then saying do not touch.

Tip: Consider using a Ticket for more safely obscuring data in a cookie on the client.

As the tip above states, you should not put secure data on the client. However, there times you may want to store data on the client via a cookie and do not want them to be able to tamper with it. ASP.Net ships with an API/object called FormsAuthenticationTicket which is used to safely manage your Forms authentication cookie. You can leverage this API and store your own information in a cookie on the client.

To do so, simply create a new FormsAuthenticationTicket, pass it a few settings, and your "secret data". From there you call FormsAuthenticationTicket.Encrypt which returns a string you can store in a cookie. Here is quick example:

string secretData = "secret"; DateTime dt = DateTime.Now; FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(1, "ticketName", dt, dt.AddDays(7), true, secretData); HttpCookie newUserCookie = new HttpCookie("theCookie"); newUserCookie.Value = FormsAuthentication.Encrypt(newTicket); newUserCookie.Expires.AddDays(7); Response.Cookies.Add(newUserCookie);

To re-use the data, simply fetch the cookie and call the FormsAuthentication.Decrypt method:

HttpCookie userCookie = Request.Cookies["theCookie"]; string secretData = null; if(userCookie != null) { FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(userCookie.Value); secretData = ticket.UserData; }

Tip: For custom ASP.Net server controls, if you need to make sure a value is persistent, use Control State and not ViewState.

As stated previously, I generally recommend disabling ViewState. As a control developer, this can cause problems since there maybe times when using something like ViewState is necessary for your control to function properly. Thankfully in ASP.Net 2.0, as a developer, you now have a new option, Control State. 

Fritz Onion has a great detailed explanation of Control State:

Control state is essentially another state repository whose contents is propagated much like view state, but the purpose of the control state repository is to cache data necessary for a control to properly function. To put it another way, behavioral state for a control should be kept in control state, and UI state (its contents) should be kept in view state. Thus in the new GridView class, you can completely disable view state, and the pagination and editing events still fire as expected.

As always, I am eager to hear your feedback, additions, and suggestions. I am working on a separate post with tips on the most important state management option, caching, which is why I avoided the topic here.

FYI, this is part three of a continuing series of ASP.Net Tips.  If you found this post helpful, you may want to check out the other posts in the series: General ASP.Net Tips and Web.config Tips.

Similar Posts

  1. ASP.Net Quick Tips - Web.config
  2. ASP.Net Quick Tips - Caching
  3. Quick Tips For ASP.Net - Part One
  • Dave Burke on on 2.27.2007 at 9:45 PM

    blog bits Ning launches. I can't give you a first-hand review because the home page has a message that

  • Daily News List Blog on on 3.01.2007 at 6:43 AM

    Scott Watermasysk with another ASP.NET Quick Tips post that I love so. ScottW on State Management.

  • Digging My Blog - Dan Hounshell on on 3.05.2007 at 10:32 PM

    Up to this point in the development of the WhatIWantMost project I have chosen to implement the simplest

  • Ancora Imparo on on 3.07.2007 at 5:02 AM

    This is part four in the ASP.Net tips series . In particular, this is a follow-up to, " ASP.Net Quick

  • Tiernans Comms Closet on on 3.07.2007 at 9:55 AM

    Ancora Imparo has a post on Caching in ASP.NET which is a very interesting and handy read. some interesting

  • Community Server Bits on on 3.11.2007 at 9:54 PM

    Scott Watermasysk with another ASP.NET Quick Tips post that I love so. ScottW on State Management.

  • Adlai Maschiach on on 3.14.2007 at 5:58 AM

    Links regarding Tips and Tricks in ASP.NET - some articles from Scott Watermasysk Quick Tips For ASP.Net...

  • Adlai Maschiach on on 3.14.2007 at 5:58 AM

    Links regarding Tips and Tricks in ASP.NET - some articles from Scott Watermasysk Quick Tips For ASP.Net

  • Develop Better on on 10.16.2007 at 8:30 AM

    ASP.Net Quick Tips - State Management

Comments

  • Holger from Germany on on 2.28.2007 at 1:32 AM

    Holger from Germany avatar

    saw a lot of these session tipps so far (even on msdnmag).

    ... but i never thought about using the HttpContext.Items Collection

    thx, and best regards from germany

  • Brett on on 2.28.2007 at 5:17 AM

    Brett avatar

    On tip #1:  Be aware that Cache doesn't work well in low memory conditions (read, all the time on a real server) and you have to use NotRemovable for the priority (and obviously a long timespan) to get the same effect as Application.

    http://www.west-wind.com/WebLog/posts/11379.aspx

  • José Lema on on 2.28.2007 at 11:53 AM

    José Lema avatar

    What about querystring parameters? Don't those count? :)

  • Sean Winstead on on 3.02.2007 at 9:14 AM

    Sean Winstead avatar

    I'm guilty of using Session storage in the past and am being weaned from it now that I work with Community Server.

    What's your advice on handling a situation where the web user is doing a lot of data entry? Let's say they're entering or editing a sales order that may have 20 line items, misc charges, and misc notes. They may cancel their changes at any time (i.e., if it already exists in the database then it should remain undisturbed until they click the Save button).

    Is that something you'd always store in cache, keyed on the order ID, with priority set such that it is never removed from cache?

  • Scott Watermasysk on on 3.07.2007 at 6:16 AM

    Scott Watermasysk avatar

    Hi Sean,

    That is the rub. Generally speaking, this is exactly why session exists; to store per user data.

    However, many developers use it to store important data which can be lost on a single app-restart, browser crash, etc. There are options for storing session on a state server or database, but then anything you place in session (even not important items) are maintained, saved, fetched on every request.

    If the data is that important to you, I would suggest saving it in the database and fetching/updating it when needed.

    HTH,

    Scott

Comments are closed