Web applications cause a problem that is not present on traditional applications stored on the user’s PC (tablet/phone). The problem is the following: the user connects to the server and requests a page, the page is delivered, the connection is stopped and then all the page objects are deleted from the server memory. This stateless design helps the server to deliver better performance while it serves a huge number of requests over a small period of time but if the users need some data for a longer period of time, they cannot achieve that unless the page code contains additional tricks.

View State

Probably the most common solution for above problem. View State is a mechanism that creates a hidden field that ASP .NET adds to the rendered HTML code of the web page. This hidden field can contain data for later usage, after the page is posted back.

How to Use View State

ViewState is a page property that provides the current view state data. It actually provides an instance of a collection class called StateBag. StateBag is a dictionaty collection (each item is stored separately and are accessed by unique string names).

Let’s see a simple example of using ViewState:

public partial class Counter : System.Web.UI.Page
{
	protected void cmdIncrement_Click(Object sender, EventArgs e)
	{
		// In this example counter has to use data calculated before the last post back
		int counter;
		// We have to check if view state contains value for our counter. If not checked, a possible null reference exception will occur
		if (ViewState["Counter"] == null)
		{
			// If view state doesn't contain such value, we assign a value to counter
			counter = 0;
		}
		else
		{
			// If view state contains previously used value, we assign it to counter and increment it by 1
			counter = (int)ViewState["Counter"] + 1;
		}
		// Saving the new value in view state
		ViewState["Counter"] = counter;
		lblResult.Text = "We counted up to: " + counter.ToString();
	}
}

View State and Security

Some developers might have inspected what hidden field view state generates. It can look similar to this:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="gHuuTRJhjTygg676Jlk78JKjhjkJHg7jkhlll099HhhhRyer=" />

The content of the value attribute might look encrypted but it isn’t. It’s just a Base64 string and some people can convert this value into something meaningful and then access important data. To solve this problem developers have two options:

  • Using hash code: ASP .NET checks the view state data, just before the final page is rendered. Then is uses a hashing algorithm to run the view state data through. By implementing some secret key a hash code is created and appended to the view state data. Then the final HTML code renders on the browser.

The reverse process is this: ASP .NET checks the view state data and calculates the hash code using the key. Then checks if this hash code is the same as the one stored in the view state data on the page. If they are the same, the original data is retrieved. If not, the postback is rejected completely.

Fig 1 View State Hashing Process

Hash codes are enabled by default and no additional work is required unless the developer has disabled them.

  • View state encryption: hash codes make original view state data encrypted but it can still be viewed by the user. If you want to hide completely this data, you should enable view state ancryption. This can be done on a single page:
<%@Page ViewStateEncryptionMode="Always" %>

Or for all pages through your web.config (usually) file:

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

viewStateEncryptionMode has three possible values. The other two are “Never” and the default one – “Auto” which will only encrypt the view state unless some control requests it by calling the Page.RegisterRequiresViewStateEncryption() method. viewStateEncryptionMode=”Never” has a larger priority than Page.RegisterRequiresViewStateEncryption().

View State and Member Variables

View state can also be used to retain member variables. The member variables have to be saved in view state once the Page.PreRender event occurs and then be retrieved once the Page.Load event occurs which happens every time the page is created. During a postback, Page.Load fires first.

Example:

public partial class RetainMemberVariables : Page
{
	// A member variable
	private string someString;
	protected void Page_Load(Object sender, EventArgs e)
	{
		if (this.IsPostBack)
		{
			// Restore variable.
			someString = (string)ViewState["someString"];
		}
	}

	protected void Page_PreRender(Object sender, EventArgs e)
	{
		// Persist variable.
		ViewState["someString"] = someString;
	}

	// Clicking on a Save button
	protected void cmdSave_Click(Object sender, EventArgs e)
	{
		// Transfering contents of a text box to the member variable.
		someString = txtTextBox.Text;
		// We can empty the text box now
		txtTextBox.Text = "";
	}

	protected void cmdLoad_Click(Object sender, EventArgs e)
	{
		// Restoring contents of the member variable to the text box.
		txtTextBox.Text = someString;
	}
}

However, developers should avoid above approach unless really necessary. Using this to store too much information will affect negatively final page output size and page transmission performance. The code may also be confusing to be read by other developers.

Storing Objects in View State

Objects can also be stored in view state. However, they must be instances of a serializable class. To make a class serializable, you should declare its serializability by using an attribute right before declaring the class:

[Serializable]
public class CustomClass
{
	...
}

When you retrieve view state data for custom objects, you should always cast it:

custom = (CustomClass)ViewState["CustomClassObject"];

Was this post helpful?