Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

ASP.NET Client and Server Site State Management

10 Jul 2014 1  
This article explains how to manage ASP.NET Client and Server State, via View State, Hidden Fields, Cookies, Query Strings, Session State and Application State.

Introduction

When working with ASP.NET, data can be persisted in the framework in several ways, which a developer must have a proper understanding. Generally speaking, information can be handled in the Client and Server side when using ASP.NET framework. For instance, hidden fields and View State manage information in the client side whereas User Session handles it in the server side.

This article aims to explain each of the mechanisms to manage data in ASP.NET. Moreover, it will discuss the appropriate usage of each one of them and encourage the reader to have a deep understanding of each one of them.

A code is provided exemplifying all the material covered here.

Client Side State Management

View State

View State is one of the most useful ways of storing data when developing for ASP.NET, because it stores variables values in the lifetime of a page. Concretely, suppose the user is in a page called PageA.aspx. The user may do several activities which involve full or partial page submissions. For instance, he or she may click in buttons or select drop down list components which cause the browser to submit the page. If the user continues in the same page, meaning post-backs were executed, then values saved in the View State will not be deleted between page submissions. Therefore, one has the ability to persist values throughout one Page´s existence, as long as the page does not change.

Another very interesting fact about View States is that they are stored in the Client Side, which means no extra data will be persisted in the Server Side. The obvious drawback, however, is that pages which use View State will get bigger which means that in the end, more bandwidth to transfer data will be needed. Below is an example of the source-code of a page and the View State.

The areas in read are the values persisted as View States. Note that they are stored in hidden fields thus making no interference with the Web Page. Moreover, observe that in this example they are small; however the bigger the View State variables are, the bigger these hidden fields will be.

Now, one might be wondering now how to store values in the View State. This is as simply as storing values in a C# IDictionary. The code below shows how to store several types of values in the View State. Note that, in order to call the View State static methods, one must be in a code-behind page.

// saving a simple Int32
ViewState["3In32"] = 3;

// saving a String
ViewState["AString"] = "My String";

// saving a serializable Object
ViewStateHolder holder = new ViewStateHolder();
holder.Value = "yet another value";
ViewState["SerializableObject"] = holder; 

Observe C# primitive and any Serializable Object at all, can be saved. Here the Custom Object ViewStateHolder was created and a String was set in its Value property. This Custom Object is from a Serializable Class, as displayed below:

/// <summary>
/// // Serializable class which can be persisted in the View State
/// </summary>
[Serializable]
public class ViewStateHolder
{
    public String Value { get; set; }
} 

In order to get the values from the View State, simply retrieve them by their keys and get their values, as shown below:

// get a simple Int32
Int32 int3Value = (Int32) ViewState["3In32"];

// get a String
String myString = (String) ViewState["AString"];

// get a serializable Object
ViewStateHolder holder = (ViewStateHolder) ViewState["SerializableObject"]; 

Therefore, as one may observe, handling View States is quite straightforward making this tool quite useful and yet pretty simple to use.

A note about security: View States are nothing more than fancy hidden fields, hence avoid storing sensitive data here because they can be tampered. Although View States are hashed, encoded and include a Message Authentication Code - MAC, it is strongly advisable to keep confidential data in the server side. If you must have sensitive information in your View State, you can encrypt it, either in your page (using ViewStateEncryptionMode property of the Page Object), either for the entire application in the Web.Config file, as shown:

<configuration> 
 <system.web>
  <pages viewStateEncryptionMode="Always"/>
 </system.web>  
</configuration>  

Hidden Fields

Hidden Fields are well known tags for Web Developers. As a simple HTML component, it simply serves the purpose of storing data so the user cannot see it. This data is to be sent to the server. Note that as ordinary HTML elements, hidden fields do not live for the whole existence of a Web Page, as View States do. In order for that to happen, the values in the hidden fields have to be manually persisted every request.

There is however, the ASP.NET Control HiddenField. This, as any other ASP.NET control, has the ability to maintain its life throughout a Web Page´s many requests, as long as the application does not leave the Page. Below is displayed how one declares a hidden field in an ASP.NET Page.

<asp:HiddenField ID="hdnHiddenField" runat="server" />  

And below is displayed how to set a value, in the Code-Behind for the hidden field declared above.

hdnHiddenField.Value = "A String to be stored";  

As View States, hidden fields are saved in the Client-Side, therefore they must not hold secure information. Furthermore, HiddenField ASP.NET controls are transformed into simple hidden field tags in the HTML page, with no hashing or encryption whatsoever.

Cookies

A cookie is a small amount of data written in the client-side (the browser stores it in the file system), which is passed to the server for each request made for a specific site.

The process of creating and using a Cookie works as follows:

  1. The browser makes a request to a Server for the first time - no Cookie is used here because the browser still does not know the Server.
  2. The Server responds to the browser with a Request, providing a Cookie to the browser.
  3. The browser then stores the received Cookie in the client machine, usually in a small file in the File System.
  4. The browser makes Requests to the Server using this very Cookie. This allows the Server to identify a specific client.

As stated in the process above, using Cookies is a very nice manner to identify a client which is using the application, meaning a certain user. This is, actually, the main usage for Cookies, to identify users of an application throughout many requests. This could go on for days, depending on your Cookie duration. Below is displayed how to create a Cookie, in the Response object of the ASP.NET, because as the steps shown above, Cookies are created and have their values set by the server side, in the Response.

Response.Cookies["LastTimeVisited"].Value = new DateTime().ToLongDateString();
Response.Cookies["LastTimeVisited"].Expires = new DateTime().AddDays(1);

Note in the code below the Cookie identified by the String "LastTimeVisited" is set holding the value of the current date in the server. Moreover, its expiration date is one day after the Cookie is created. After creating Cookies, it is time to read them, the code below shows how to do so:

// if there is a cookie, show its value which is the last time the site was visited
if (Request.Cookies["LastTimeVisited"] != null)
{
    // use HtmlEnconde just to make sure no malicious string is set here
    lblLastVisitedDate.Text = Server.HtmlEncode(Request.Cookies["LastTimeVisited"].Value);
}

Note in the code above, that if the Cookie is created, its value is set in the label named lblLastVisitedDate. It is always a very good practice to check whether Cookies do exist because they may not have been created or may have expired.

There are a few important rules about Cookies, shown below:

  • If you do not set the expiration date of the Cookie, when the browser is closed, the Cookie is deleted from the navigator.
  • You cannot delete a Cookie, per say; however, if you set the expiration date to a date previous to the current one, the Cookie is removed from the browser.
  • Cookies are limited to your domain. Meaning browsers cannot use or send Cookies across domains, because this would be considered a security breach.

There are more things you can do with Cookies, such as limit the scope of the Cookie usage for a web pages in a directory in the Server Side, and save multiple values in a Cookie itself. However, this will be left to another discussion since the idea here is to show the basics on how it works.

As with View States, Cookies are quite easy to handle in the ASP.NET framework and its usage for user-specific purpose should be explored.

Query Strings

Query Strings are quite known structures for web developers. They are elements appended in the browser´s URL. These elements are pairs of key/values which are represented as follows:

  • A question mark (?) is added in the end of the URL.
  • After the question mark (?), a key is written and its value is set after a sign of equals (=).
  • If one wishes to add another pair of key/values, simply put an Ampersand (&) and another key/value pair separated by the equals (=) symbol.
  • To add other key/pair values, simply follow the step below.

Here is an example of a URL with Query String: http://www.mysite.com?key=abc&key2=s323&key3=abcd. Note that in this example, there are three keys: "key", "key2" and "key3" with their respective values: "abc", "s323" and "abcd".

Query String key/values are sent to the server and them processed by it. They are explicitly displayed in the URL, thus if one whishes to pass sensitive data, this is not the best place.

Query Strings are quite useful to bookmark a page state. For instance, if one has search page which parameters are passed via Query Strings, one can bookmark this page and use it to reproduce the same result later.

Below is displayed how to read Query String in ASP.NET Code-Behind pages:

// read values from the URL: http://www.mysite.com?key=abc&key2=s323&key3=abcd
String queryStringValue = Server.HtmlEncode(Request.QueryString["key"]); // read value is abc
String queryStringValue2 = Server.HtmlEncode(Request.QueryString["key2"]); // read value is 5323
String queryStringValue3 = Server.HtmlEncode(Request.QueryString["key3"]); // read value is abcd

Note how straightforward it is to read these data using ASP.NET. If there is no key represented by the entered String in the QueryString IDictionary, null is returned. Moreover, Server.HtmlEncode was used in order to avoid malicious text to be entered.

Also observe that if you always process a page with the same Query Strings values in the same fashion, one can use this page with Query Strings as a bookmark which contains a certain state of the application. For instance, imagine one wishes to save specific search results of an application. If it handles the same URL and Query Strings in the same manner, everytime they are sent from the browser, this search can be book marked.

An important remark is that browser´s URL have a maximum limit size, around 2000 characters, so be careful not to produce too long strings in which this limit is exceeded.

As a final observation, Query Strings are sent to the server via GET HTTP method. Note that this was not discussed here because classic ASP.NET development does not go much in these details. Obviously, with the new tendency of writing REST Application and going back to simple Web Application using the HTTP protocol as it is supposed to be handled, GET, POST, PUT, etc. HTTP methods became quite relevant nowadays.

Server Side Sate Management

Application State

Application State saves data throughout the life of an application, from the time IIS (Internet Information Services) is started to the time it is shutdown. Data saved here can be used throughout all user sessions as long as the application has not been shutdown. Thus, one of its main purposes is to create Application Cache. However, since this data storage lives during the whole Application life-cycle, this feature must be used wisely, in order not to consume too much of the Server resources.

In order to store data, simply do as in almost all other cases, as the code below shows (note you must be in the code-behind in order for the code to work):

// store value in the Application State
Application["myAppStateString"] = "my text";

// retrieve value from the Application state
String myText = (String) Application["myAppStateString"];

Note again, how straightforward it is to store and retrieve values from the Application Session, using keys to identify the value being saved. Also, as with View States, one can store any Object which is Serializable.

Observe that data stored in the Application Session is never sent to the browser, so sensitive information can be saved here safely.

In order to exemplify the usage of this state, imagine the following example: suppose one wishes to count how many users have logged in throughout the life of the application. In order to do so, when the application is started, a counter should be initialized with zero. Whenever a user logs in, the counter must be incremented by one. Here, one does not consider the matter of whether the same user logs more than once. Finally, when the application is closed, this data can be persisted in the database.

As stated, the first thing to be done is to initialize a counter when the application is started. This is done in the Application_Start event in the Global.asax class, as displayed below:

public class Global : System.Web.HttpApplication
{
    /// <summary>
    /// Event called when the application is started.
    /// </summary>
    /// <param name="sender">Sender</param>
    /// <param name="e">Event arguments</param>
    protected void Application_Start(object sender, EventArgs e)
    {
        Application["nUsersCounter"] = 0;
    }

     // other events
}

Now, whenever a user logs in, the same counter must be incremented. Below is the event called when the user is logged successfully, and the counter is incremented.

/// <summary>
/// Event called when the user tries to log in.
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
protected void btnLogin(object sender, EventArgs e)
{
    // complex code where the user is authenticated successfully
    if (authenticationSuccessful) {
        // get the counter from the application state, increment int and add it back to the application state
        int counter = (int) Application["nUsersCounter"];
        counter++;
        Application["nUsersCounter"] = counter++;
    }
}

Finally, when the application ends, the Application_End event of the Global.asax is called and the data is to be stored in the database, as displayed below:

public class Global : System.Web.HttpApplication
{
    // other events

    /// <summary>
    /// Event called when the application is terminated.
    /// </summary>
    /// <param name="sender">Sender</param>
    /// <param name="e">Event Arguments</param>
    protected void Application_End(object sender, EventArgs e)
    {
        int counter = (int)Application["nUsersCounter"];
        // persist data in the database
    }
}

Session State

Session state hold values in the scope of a user life-cycle. It means that when a user is authenticated in the application, as long as the user is logged in, it will have a Session State to store values. When the user logs off, these values are lost. Thus, this is quite useful to store user specific information. Moreover, since no interaction with the browser is made here, this is ideal for storing sensitive information.

Below is an example of how to add values to the Session State, as well as how to retrieve them.

// store value in the Session state
Session["mySessionStateString"] = "my text";

// retrieve value from the Session State
String myText = (String) Session["mySessionStateString"];

As one can notice, this is exactly most of the cases shown here. Again, as with Application and View State, Serializable Objects can be stored in the Session State.

Here an example is given in order to make the understanding of this state more concrete. Suppose you wish to retrieve all purchases of a user based on its login. In order to do so, whenever a user logs in the application, its login can be stored in the Session and when his or her purchases are to be retrieved, simply get the login from the Session and use it to query the database.

Below is how one stores to user login in the session when he or she is logged in.

/// <summary>
/// Event called when the user tries to log in.
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
protected void btnLogin(object sender, EventArgs e)
{
    // complex code where the user is authenticated successfully
    if (authenticationSuccessful) {
        // Store the user in the Session
        Session["login"] = txtLogin.Text; // retrieve the login from the TextField component called txtLogin
    }
}

Now in order to query the database, when the event of retrieving purchases is called, get the login from the Session and use it to query the database.

/// <summary>
/// Event called one whishes to retrieve all purchases related to a user
/// </summary>
/// <param name="sender">Sender</param>
/// <param name="e">Event arguments</param>
protected void btnGetPurchases(object sender, EventArgs e)
{
    String login = (String) Session["login"];
    // instantiate the business object and retrieve the list or purchases related to a login
    PurchaseBusiness purchaseBusiness = new PurchaseBusiness();
    IList<PUrchase> purchaseList = purchaseBusiness.GetPurchasesByLogin(login);
    // bind list of purchases - purchaseList to adequate control.
}

Code Sample

One can download the sample code and see examples of all which was explained here. Since the code is quite simple, there is no need to go into details on how it works. A beginner ASP.NET developer should fully understand it, provided he or she has read this article. The code is also commented, in order to make its understanding easier.

Discussions

In this article was presented manners of persisting data in an ASP.NET application, in client and server side.

The first thing to observe is that sensitive information should not be stored in the client side. If that is really necessary, do so in the View State using encryption, otherwise store this sort of information in either Application or Session State.

Moreover, note the variety of manners to handle data in the client side. The advantage of knowing and using this mechanism is that JavaScript is kept to a minimum since User Interface handling can be done via Ajax Controls, and data can be stored using one of the State Storage frameworks discussed here.

Furthermore, note that ASP.NET development uses these features so the developers do not have to worry with issues of how to handle data in the HTTP protocol context. For instance, if the developer intends to keep data alive for a page life-cycle, he or she can use View State. If something simpler is needed, Hidden Fields can be used. On the other hand, if user specific information must be handled, Cookies or Session State mechanisms may be utilized.

Also, it is important to wisely define what will be stored in the client and in the server side, according to a performance point of view. Keep in mind that storing information in the server side will add an extra workload to the server, thus diminishing its performance. Hence, it is advisable to store only information which makes sense for a user or application scope. In the client side, one has to be careful not to keep too much information in the page, because it may get too big which will require a lot of internet bandwidth and workload for the browser. Therefore, whenever possible, retrieve information from the database instead of keeping it in the client side, if this does not cause performance issues. Note that this topic is very abstract and no definitive answers are provided. This is because this sort of issues must be addressed on a case by case situation, and only experience helps developers to make the best decision.

To conclude, State Management in ASP.NET is one of the features that makes it quite productive because handling data for Web Application becomes much easier.

History

  1. First version
  2. In the Session State code example, Application was being used instead of Session. This is now corrected. Moreover, the brief introduction was also altered with more precise names.
  3. Added more tags and more items to the final discussion.
  4. Added examples for Application and Session State, as suggested by a user in the forum. Moreover, a small example was also added in the Query String explanation.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here