Managing State in ASP.net

Managing state is possibly the most important thing any web developer has to do. A basic request to any web server has no concept of state – and if the developer has not explicitly specified this then each request will be treated as if it was the first time the user had ever made a request. It might be that this is absolutely fine: Small, static projects may have no need to explicitly manage state. Most projects or applications, however, will.

Now: This article is by no means going to go into the topic in great detail. There would be absolutely no need for me to do that because there is already a wealth of information out there. There is an absolutely fantastic article over on the MSDN and if you want a more in-depth explanation of state management, I would recommend you stop reading this and go and read that instead. Although, the concept of state management is not limited purely to sites and applications developed with Microsoft technology, their guide is the best I‘ve seen.

What I will instead do here is give a very brief overview of some of the methods of state management, Show an example of using each, bullet out some pros and cons of each and give some real-world examples of when you might use each one. I do expect this article to evolve over time, so if you’re reading this close to post date expect it to go through several revisions (and suggestions are most welcome).

This is also a fairly basic topic so apologies in advance: I’ve been writing applications for years but am relatively new to writing articles so am practicing on the basic topics first.

Session

You can think of a Session beginning when the user “first visits“, and ending after they’re “done”. The concept of a user being “done” is a decision that the developer needs to make themselves: it is determined by a period of inactivity from the user since their last request. At time of writing, the default period of time is 20 minutes. Session actually works by sticking a small cookie on the client’s machine (more on cookies later) containing a session ID. This ID corresponds to an ID server-side which again you can choose to either store “In Process”, in a SQL database or on a state server. Whichever of these choices you make, the basic idea remains the same.

Example

It’s just a collection, accessible through properties of the Request, Page and HttpContext
objects among others. You use it just like any other collection;

Put something in…

Session["Foo"] = "Bar";

And take something out…

String bar = (string)Session[“Foo”];

Pros

  • Put something in Session, and it’s accessible at any point during the user’s visit to your site.
  • It can store complex objects (although you need to cast on retrieval as above)

Cons

  • Not Scaleable: Data is stored server side.
  • State is lost if application pool is rebooted for any reason.

Real world Application

  • Shopping trolley for the duration of a user’s visit.
  • Authentication / Remembering if a user is logged in or not.

Other considerations

While the concept of session will remain the same, you will additionally have to consider where you’ll store the session data itself. As previously mentioned, ASP.net allows you to store this in three different ways and the one you choose will basically be determined by how much traffic you’re expecting to get and how big your session objects are going to be. See the MSDN article for more info about these considerations.

Application

Not to be confused with Session, although very similar. You can access it through a property of the page object, and it survives until the application terminates. If you are storing your state data “in process”, this is essentially the same thing although application state can not be stored in a SQL database or on a session server.

Example

Like session, It’s just a collection (although this time you can‘t access it through the request). You use it just like any other collection;

Put something in…

Application["Foo"] = "Bar";

And take something out…

String bar = (string)Application[“Foo”];

Pros

  • Accessible at any point during the user’s visit to your site.
  • It can store complex objects (although you need to cast on retrieval as above)

Cons

  • Not Scaleable: Data is stored server side.
  • State is lost if application pool is rebooted for any reason.

Real world Application

You should use application state to store things that aren’t specific to the user or their visit. So, whilst a “shopping cart” is appropriate for session, it’s not appropriate for application. Things that *are* suitable are;

  • A database connection string
  • A third party web service or widget’s username or password

Commonly people will fish these things out of their web.config file on the “application start” event and put them into application object.

Cookies

Cookies are small key-value pairs that you can deposit onto the client’s machine through the web response. Any given cookie has an “expiry date” that you set when you serve one to the client. You can’t just store these things forever on a clients PC – by default the cookie expiration time is set to the same as the session expiration time, which is 20 minutes after the last request. Commonly though, with cookies you‘ll want to extend this period of time, the reason for which will become obvious when you see the real-world uses for cookies.

One other thing: Many developers seek to create cookies that never expire. This is not actually possible: the date of cookie expiration is send back through the response and stored on the clients PC. You can sort of achieve it by setting a ridiculously distant expiration date (say, 50 years) but this is generally bad practice because if someone isn’t going to visit your site for 49 years then you shouldn’t be giving them a cookie in the first place. A better approach is to “top up” the expiration date of the cookie every time a user visits your site, and limit this period of time to no more than 3 years maximum.

Example

There’s a property of the Repsonse object that you can use to send cookies back to the user;

Response.Cookies["foo"] = "bar";

And you can retreive the cookie from a request…

string bar = Request.Cookies["foo"]

Pros

  • Scaleable (data stored on client machine)
  • Long expiration dates are allowed

Cons

  • Limited to 4KB in current browsers
  • Users can block them AND change them
  • Not secure (don’t use for passwords)

Real world Application

  • Tracking user conversions: If a user first visited your site on Monday, but didn’t convert until Friday, you might want to know that they *originally* visited through one of your PPC campaigns. You wouldn’t be able to tell this unless your application remembered their first visit.
  • Multivariate / AB testing (so your user doesn’t see all tests, you would need to assign them a ‘toss of the coin’ on the first visit and retain that throughout their experience)
  • Remembering login credentials (remember the original point about security though)
  • Cookies are used to power the aforementioned session state.

ViewState

Viewstate is a method by which you can maintain information during a postback (where a page is its own referrer). This is done by putting a hidden encoded hidden field in the HTML response, which the client then sends back to you on their next request. For this reason, it should be obvious that large view state data will mean large requests and therefore will increase traffic size.

Example

Again, view state is accessible through properties of the Request, Page and HttpContext
objects among others, and is just a collection;

 if (!this.IsPostBack)
{
        ViewState["foo"] = "bar";
}
else
{
                string bar = ViewState["foo"];
}

Pros

Scope limited to single postback, then it’s gone, so no lingering memory usage.

Cons

  • Increases traffic so data size should be kept small.
  • Can only be used in post-backs, then it‘s gone (I know this is a pro as well, but there you go).

Real world Application

  • Step-by-step wizards, such as checkout pages
  • “Contact us” forms, which handle procurement as well as usage of information from the user

QueryString

This is the method by which you include (possibly) state related information within the URL of the request. They take the following form;

http://www.mytestsite.com/apage.html?akey=avalue&anotherkey=anothervalue

You will then be able to access each key/value pair stored in the request.

Example

Given the above example, the values would be accessible from within the request using the following;

string aValue = Request.QueryString["akey"].ToString();

Pros

  • State can exist within links to your site.
  • User can not “disable” query string values in their browser settings (they’d have to physically delete the details from the URL, which they can’t do by accident)

Cons

  • Size restrictions in some browsers
  • Limited to simple strings (certain characters, such as ? Or &, are illegal in URLS)

Real world Application

  • Achieving simple dynamic content by passing an ID through the query string and accessing a database to retrieve content relavant to that ID (be VERY wary of SQL injection when anything from the query string ends up near a database)
  • Tracking where a user has come from (e.g. a banner ad may link through with a bunch of query string information that you want to record)
  • External links that may want to pre-fill or pre-prepare the resultant page (such as a link with an activation code that you have emailed to someone, may automatically “activate” something when the user clicks the link)

Forms

The HTML form tag provides a facility for you to make details available in the request that follows the submission of that form. Unlike view state, information stored in a form is available from any page that the “action” attribute of that form sends the subsequent request to, and is not just limited to post backs. HTML forms can also have hidden fieds that are handled in the exact same way on the resulting page as non-hidden fields. This should go without saying, but hidden fields on a form are only hidden from the user’s ‘view’, and are in fact perfectly un-hidden if the user views the source of the page, so no sensitive information should ever go in them unless it is sufficiently encrypted.

Unlike other state management techniques that are described here, this one is interwoven with the HTML structure of your site. As a result it can be styled and used semantically as a “form” but this does not mean that you must use it in this way. A common practice is to have one form on a page and many actions that would submit that form. For example, if you had a page of products that a user could potentially add to their basket, it’s far simpler to have one form and allow many buttons to submit that form through javascript than it is to have many forms.

Example

A form with any input with the ID of ‘foo’ would be accessed through the request as follows;

string bar = Request.Forms["foo"].ToString();

Pros

  • Achieves (internally to your site) same result as query string without causing complex URLs.
  • Resultant request can be interrogated regardless of which page was the referrer.

Cons

  • Limited to simple strings (certain characters, such as quotation marks, are illegal in forms)

Real world Application

  • “Add to cart” buttons
  • “Contact us” forms

The ASP.net Request object

The ASP.net object is a collection itself; and can be used in the following manner;

string foo = Request["bar"].ToString()

This will actually interrogate the entirity of the request object (including Querystrings, Cookies, Forms and Session) for a value with a key corresponding to the one asked for. I don’t know where it looks first (if you know, please tell me out of curiosity) but the order should not be a consideration you need to be making: It may be that you want to look through the enire request for your key but in 99% of cases you will want to specify where you are looking and any decision to use the above functionality should be a concious one due to the inherrent serurity vunerabilities caused by the ambiguity.

Conclusion

Managing state should be at the forefront of your mind during web application development. There are numerous techniques at your disposal to achieve this, each with appropriate uses. Make every decision a concious one to achieve the most scaleable, secure and bug free application you can.

Advertisements

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