State Management Basics in Asp.Net

This tutorial explains state management in ASP.NET applications and introduces the techniques for the state management including View State, Session, Cookie, and Query String.

When you work on a desktop application, the application continuously runs by using the resources of your computer. Certain portion of your computer’s memory is allocated for the use of the application. However, web applications work differently. Web applications serve to a large number of users which could change from a few to a billion. The server has to use its own resources wisely to process user requests. Web servers destroy all the page objects created in the memory to process user requests. In other words, by the time the rendered html output is sent to the client from the server, the memory allocated for processing the client request is already voided to be able to process other requests. The more the memory is readily available, the higher number of requests the server can process and the faster it can get in processing. Therefore, ASP.NET is stateless. Server does not maintain any information regarding the user requests in its memory as opposed to for example desktop applications.

Hopefully, there are several techniques in ASP.NET that help address limitations of stateless nature.

View State

View State is a client-side state management mechanism that stores the intended data in a hidden field and the stored information travels back and forth during post backs. View State is used to persist the information in the same page. In other words, it provides page-level state management. When navigated to a different page, the current information in the View State will be lost.

View State can store simple data types (e.g., integers, strings) as well as objects. However, it is not recommended to store objects in View State because of the overhead of serialization and deserializion on the server side. Also, storing big data in View State has some performance penalties since the whole View State is transferred back and forth between the server and the client in every post back event, occupying the bandwidth.

View State uses a dictionary to store data. Every data instance is stored in a separate slot using a key which should be a unique string name. The following example shows how to use View State to store a number and increment it by 1 in every button click.

if(ViewState["myCount"] != null) //if count is created before
{
    int count = Convert.ToInt32(ViewState["myCount"]); 
    count++; 
    ViewState["myCount"] = count; 
    lbl_Print.Text = "Count: " + count.ToString(); 
}
else//if the count will be created first time
{
    ViewCount["myCount"] = 0;
}

In this scenario, the state of the count variable will be maintained in View State, traveling between the client and the server in each button click. If the user navigates to another page, the count variable will be lost.

Cookies

Cookies provide client-side state management. A cookie is a simple text file stored in the users’ local hard drive. A cookie accompanies the request sent from the browser to the server. It will also accompany the response from the server if create a cookie or if we need to modify/delete a cookie.

Let’s see how cookie works with an example. We will create a cookie that stores the name entered by the user, and display the name automatically next time the user visits the page. When clicking the button, the cookies will be updated. The interface should look like this:

1

There are two ways to create a cookie. The following code creates a username cookie using the first method and a lastvisit cookie using the second method. Please place the following code to the click event handler of the button:

//First way
Response.Cookies["username"]Value = txt_Username.Text;
Response.Cookies["username"].Expires = DateTime.Now.AddDays(2);

//Second way
HttpCookie nameCookie = new HttpCookie("lastvisit");
nameCookie.Value = DateTime.Now.ToString();
nameCookie.Expires = DateTime.Now.AddDays(1);
Response.Cookies.Add(nameCookie);

With the code above, we are recording the username and the last visit time when the button is clicked, overwriting the existing cookie if already created. This is also how you update a cookie.

Let’s create a method, DisplayCookies to display the cookie values on the label, and call the method from the Page_Load:

public void DisplayCookies()
{
     if (Request.Cookies["username"] != null)
     {
          lbl_Info.Text = Request.Cookies["username"].Value + " visited - " +
          Request.Cookies["lastvisit"].Value;
     }
     else
     {
          lbl_Info.Text = "First access.";
     }
}

In the code above, we first checked if a cookie with “username” exists or not. Note that we used Request object instead of Response. This is because we are reading the request sent from the client, and if any cookie is created before, it should travel within the request object, and therefore we should be able to access it through the Request object. On the other hand, when we create/update a cookie, we need to use Response object. This is because, when server evaluates the request of the client, it will prepare a Response to be sent to the server, which is generally an html page. This response also carries the created/updated cookie back to the client browser.

Below we call DisplayCookies() method from the page load event:

protected void Page_Load(object sender, EventArgs e)
{
    if(Page.IsPostBack == false)
        DisplayCookies();
}

Let’s test it:

2

After a cookie is created, you can view it from your browser settings. In Chrome you can press CTRL + SHIFT + DEL. Then at the bottom of the window choose Content Settings. After that, in the new window click on the All Cookies and Site Data. You should be able to access the cookie using localhost in the search box:

3

How about deleting a cookie? Cookies are stored in local computers’ hard drive. However, our ASP.NET application cannot perform a delete operation on the users local drive. What we can do is to ask the browser to delete a cookie. If we set the expire date of a cookie to previous day, or hour, or even second, then the browser will check if the cookie expired or not, if expired then the browser will delete the cookie.

To implement deleting cookie functionality, please add a button and name it btn_Delete, and write the following code for its click event handler:

protected void btn_Delete_Click(object sender, EventArgs e)
{
     //Delete individual cookie instances
     Response.Cookies["username"].Expires = DateTime.Now.AddDays(-2);
     Response.Cookies["lastvisit"].Expires = DateTime.Now.AddDays(-2);
     DisplayCookies();
}

Advantages and Disadvantages of Cookies (source: MSDN)

Advantages of using cookies are:

  • Configurable expiration rules: The cookie can expire when the browser session ends, or it can exist indefinitely on the client computer, subject to the expiration rules on the client.
  • No server resources are required: The cookie is stored on the client and read by the server after a post.
  • Simplicity: The cookie is a lightweight, text-based structure with simple key-value pairs.
  • Data persistence: Although the durability of the cookie on a client computer is subject to cookie expiration processes on the client and user intervention, cookies are generally the most durable form of data persistence on the client.

Disadvantages of using cookies are:

  • Size limitations: Most browsers place a 4096-byte limit on the size of a cookie, although support for 8192-byte cookies is becoming more common in newer browser and client-device versions.
  • User-configured refusal: Some users disable their browser or client device’s ability to receive cookies, thereby limiting this functionality.
  • Potential security risks: Cookies are subject to tampering. Users can manipulate cookies on their computer, which can potentially cause a security risk or cause the application that is dependent on the cookie to fail. Also, although cookies are only accessible by the domain that sent them to the client, hackers have historically found ways to access cookies from other domains on a user’s computer. You can manually encrypt and decrypt cookies, but it requires extra coding and can affect application performance because of the time that is required for encryption and decryption. For more information, see ASP.NET Web Application Security and Basic Security Practices for Web Applications.

Query Strings

Query String has limited capability for state management. However, they are simple and easy way to pass values across pages. In other words, they help maintain state between pages, which was not possible with View State.

A query string is simply a pair of attribute and value that is attached to the url of a page with   ?   sign, as seen in the following code.  ?  is used only for the first instance of query string. When attach more than one query strings,  &  should be used preceding the attribute name:

www.mysite.com/GetCourses.aspx?department=EDIT&credithour=3

There are two query strings defined in the url above: one has department/EDIT attribute/value pair, and the other one has credithour/3 attribute/value pair.

Let’s do a simple exercise to see how we can use the query string. First we need to create a Course class:

public class Course
{
    public int Id { get; set; }

    public string CourseCode { get; set; }

    public int CreditHour { get; set; }
}

Then, add a list box to the web form:

4

Then, write the following code in the page load to put some course items in the list box:

if(Page.IsPostBack == false)
{
     lsts_Courses.DataSource = new List<Course> { c1, c2 };
     lsts_Courses.DataValueField = "Id";
     lsts_Courses.DataTextField = "CourseCode";
     lsts_Courses.DataBind();
}

Also create a new web form called DisplayDetails.aspx:

5

Now, we want to navigate to DisplayDetails.aspx page with the Id information of the selected course. We will use query string to transfer the id of the selected course to DisplayDetails.aspx page. Please make sure AutoPostBack is enabled for the list box, then please double click on it, and add the following code to its index-changed event handler:

protected void lsts_Courses_SelectedIndexChanged(object sender, EventArgs e)
{
     string selectedId = lsts_Courses.SelectedValue;
     Response.Redirect("DisplayDetails.aspx?courseid=" + selectedId);
}

We used Response.Redirect() method to redirect a request to a different URL. Our query string has courseid/selectedId attribute/value pair. The following code in DisplayDetails.aspx page shows how you read the query string back in the server for some processing:

protected void Page_Load(object sender, EventArgs e)
{
     string id = Request.QueryString["courseid"];
     lbl_Course.Text = id;
}

If we had a database, we would use this id to retrieve the course from the database and display it in the edit form.

Although we do not have database connection int this example, what if we could store the list of courses and access the list later in the DisplayDetails.aspx page? We can do this by using session state.

Session State

Session is a server-side method for maintaining state in your web application. Every user connecting to the server will have its own session created: The scope of the session is the current browser session. For each different user, there will be a different session state. If a user leaves the application until timeout happens, then re-access the application, a new session will be created for the user.

The server maintains the state of user information by using a session ID stored in a cookie by default. This way, when the user accesses the web application, the web server can recognize the user and allow access to the session object allocated for that specific user.

Session state is a dictionary object with Key/Value pairs. Every user will have their own session dictionary.

You can configure the session properties in Web.Config file:

<sessionState mode="InProc" //InProc:use server memory to store the session //It could be stateserver (saving state information on another server) // or sqlserver (saving state information on the database) stateConnectionString="....." //when using another server to store the session, enter the address of the server sqlConnectionString="....." //when using sql server to store session, enter the address of the server timeout="100" //if user is inactive for 100 mins, the session will be destroyed />

Let’s change our previous example and store our courses list in the session:

protected void Page_Load(object sender, EventArgs e)
{
    if (Page.IsPostBack == false)
    {
        Course c1 = new Course() { Id = 1, CourseCode = "EDIT2000", CreditHour = 3 };
        Course c2 = new Course() { Id = 2, CourseCode = "EDIT3000", CreditHour = 5 };

        List<Course> courses = new List<Course> { c1, c2 };
        lsts_Courses.DataSource = courses;
        lsts_Courses.DataValueField = "Id";
        lsts_Courses.DataTextField = "CourseCode";
        lsts_Courses.DataBind();

        Session["courses"] = courses;//NEW CODE
     }
}

Previous time by using query string we were able to display the Id of the selected course in DisplayDetails.aspx page. Now, let’s retrieve the course object from the Session and display its name in the label:

protected void Page_Load(object sender, EventArgs e)
{
      int id = Convert.ToInt32(Request.QueryString["courseid"]);

      List<Course> courses = (List<Course>)Session["courses"];

      Course courseToUpdate = courses.Single(c => c.Id.Equals(id));

      lbl_Course.Text = courseToUpdate.CourseCode;
}

protected void btn_Back_Click(object sender, EventArgs e)
{
      Response.Redirect("Default.aspx");
}

Anything you store in the Session will be stored in the memory. If your application has a large number of visitors and if you do not use the Session wisely, this might result in severe performance penalty since the memory of the web server will be consumed rapidly.

Advantages and Disadvantages of Sessions  (source: MSDN)

Advantages of using session state are:

  • Simple implementation   The session-state facility is easy to use, familiar to ASP developers, and consistent with other .NET Framework classes.
  • Session-specific events   Session management events can be raised and used by your application.
  • Data persistence   Data placed in session-state variables can be preserved through Internet Information Services (IIS) restarts and worker-process restarts without losing session data because the data is stored in another process space. Additionally, session-state data can be persisted across multiple processes, such as in a Web farm or a Web garden.
  • Platform scalability   Session state can be used in both multi-computer and multi-process configurations, therefore optimizing scalability scenarios.
  • Cookieless support   Session state works with browsers that do not support HTTP cookies, although session state is most commonly used with cookies to provide user identification facilities to a Web application. Using session state without cookies, however, requires that the session identifier be placed in the query string, which is subject to the security issues stated in the query string section of this topic. For more information about using session state without cookies, see ASP.NET Web Site Administration.
  • Extensibility   You can customize and extend session state by writing your own session-state provider. Session state data can then be stored in a custom data format in a variety of data storage mechanisms, such as a database, an XML file, or even to a Web service. For more information, see Implementing a Session-State Store Provider.

Disadvantage of using session state are:

  • Performance considerations   Session-state variables stay in memory until they are either removed or replaced, and therefore can degrade server performance. Session-state variables that contain blocks of information, such as large datasets, can adversely affect Web-server performance as server load increases.

Application State

Application state is also a server state management technique that uses server memory to store the session objects. Application state differs from Session state in that the scope of Application session is application wide, therefore it is shared among all connected users. When you need to store small amounts of data that is needed frequently and that does not change from one user to another, then using session state would be a good choice.

Application State, similar to Session State and View State, is a dictionary object and uses key/value pairs to store some data. Here is an example:

Application["IsSiteDown"] =  "True";

var isSiteDown = Application["IsSiteDown"];

Leave a comment