Home
    Shop
    Advertise
    Write For Us
    Affiliate
    Newsletter
    Contact

ViewState in ASP.NET 2.0

One of the most interesting features of ASP.NET 2.0 is the open way it allows the programmer to manipulate a control's viewstate. The viewstate should be the first choice to save data to access across postbacks.

If the information is to be shared across different controls, it can be placed in the viewstate of the page, if it is to be accessed within the scope of a single control, then it can be placed within the viewstate of the control. The type of info one can save here may be simple data types or even complex user defined objects!

The ASP.NET Page Life Cycle

In order to understand how to use the viewstate properly, it is necessary to understand the ASP.NET page lifecycle. Whenever a page is requested from a server, it passes through the following steps:

1. The Page object is created. It contains all the same values as defined in the .aspx files. All objects/user controls placed within it are created one by one. For example, if we have a textbox on the .aspx file,

<asp:TextBox runat="server" id="tb1">TheValue</asp:TextBox>

After this stage, this textbox will have the value "TheValue"inside it.

2. The state of the page is restored based on the viewstate. If on the client side, the value of our textbox has been changed, it will now have the new value. (Obviously, this stage does not happen when the page is requested for the first time)

3. The Page_Load event is fired, at this point, the programmer can write the custom code.

4. The appropriate event handler (if any) is fired.

Storing Simple Data Types in the ViewState

Like most types of state management in ASP.NET, view state relies on a dictionary collection, where each item is indexed with a unique string name. For example, consider this code:

ViewState["ViewStateVariableName"] = 1;

This places the value 1 (or rather, an integer that contains the value 1) into the ViewState collection and gives it the descriptive name ViewStateVariable. If there is currently no item with the name ViewStateVariable, a new item will be added automatically. If there is already an item indexed under this name, it will be replaced.

You can access this variable anywhere within the page/control where the viewstate variable has been added. When retrieving a value, you use the key name.

int number = (int) ViewState["ViewStateVariable"];

You also need to cast the retrieved value to the appropriate data type. This is because the ViewState collection stores all items as generic objects which also give you the flexibility to store any type of basic data types in it. In fact, you can even store your custom objects in the view state.

Storing Objects in View State

You can store your own objects in view state just as easily as you store numeric and string types. However, to store an item in view state, ASP.NET must be able to convert it into a stream of bytes so that it can be added to the hidden input field in the page. This process is called serialization. If your objects aren't serializable (and by default they aren't), you'll receive an error message when you attempt to place them in view state.

To make your objects serializable, all you need to do is to add the 'Serializable' attribute before your class declaration. For example, here's an exceedingly simple Student class:

[Serializable]
public class Student
{
    public string firstName;
    public string lastName;
 
    public Student(string fName, string lName)
    {
        firstName = fName;
        lastName = lName;
    }
}

Because the Student class is marked as serializable, it can be stored in view state:

// Storing a student in view state.
Student stud = new Student("John", "Doe");
ViewState["CurrentStudent"] = stud;

Remember, when using custom objects, you'll need to cast your data when you retrieve it from view state.

// Retrieve a student from view state.
Student stud = (Student) ViewState["CurrentCustomer"];

To be serializable, your classes you must meet these requirements:

• Your class must have the Serializable attribute.

• Any classes it derives from must have the Serializable attribute.

• All the private variables of the class must be serializable data types. Any nonserializable data type must be decorated with the NonSerialized attribute (which means it is simply ignored during the serialization process).

Example 1: Making a PostBackCounter

Let's say you want to keep track of the number of times a page is posted back to the server. This info can be kept inside the session, or even inside a hidden field control in the page. However, keeping it in the session forces you to clear up or reset this variable every time the user moves to a new page. Keeping it in a hidden filed or an invisible text box on the page might clutter your .aspx file with controls that can be changed by malicious users. Using the view state in this scenario is an elegant way to persist info across postbacks that will be accessible only to the programmer and the code.

Suppose our .aspx page control contains one button and one label inside the form.

<asp:Label id="Label1" runat="server"/>
<asp:Button id="Button1" runat="server" OnClick="Button1_Click"/>

On the code behind file we have the page load event and the event handler for the click event of button1.

protected void Page_Load(object sender, System.EventArgs e)
{
    //First we check if the page is loaded for the first time,
    if (!IsPostBack)
    {
        ViewState["PostBackCounter"] = 0;
    }
    //Now, we assign the variable value in the text box
    int counter = (int)ViewState["PostBackCounter"];
    Label1.Text = counter.ToString();
}

Now, the label will always display the post back count!

Let's say we increment the post back count only when our button is clicked. In this case, we need to write some code on the button click event handler.

protected void Button1_Click(object sender, System.EventArgs e)
{
    int oldCount = (int)ViewState["PostBackCounter"];
    int newCount = oldCount + 1;
    //First, we assign this new value to the label
    Label1.Text = newCount.ToString();
    //Secondly, we replace the old value of the view state so that the new value is read the next //time
    ViewState["PostBackCounter"] = newCount;
}

Now, every time the user will click on this button, the text will show an incremented number!

Example 2: Tracking Dynamic Controls

One of the main challenges with working with dynamically added controls is that these controls must be programmatically added on each postback. That is, you can't just load these controls on the first page load, and then not reload them on subsequent postbacks. Failure to explicitly add the controls on each postback will cause the controls to literally disappear on postbacks.

Let's build on our previous example. Only this time, instead of an integer, we'll keep a List<string> in the view state. Instead of one label, we are going to dynamically add a new Label every time the button is clicked. And, the value of the new label will be given by the user inside a text box.

So, out .aspx page will look like this:

<asp:TextBox id="TextBox1" runat="server"/>
<asp:Button id="Button1" runat="server" OnClick="Button1_Click"/>
<asp:PlaceHolder id="PlaceHolder1" runat="server" />

The placeholder will act as the container on which we shall load out Labels.

On the code behind cs file, we have page load event, which initializes the controls:

protected void Page_Load(object sender, System.EventArgs e)
{
  //First we check if the page is loaded for the first time,
  if(!IsPostBack)
  {
    List<string> temp = new List<string>();
    ViewState["allTextData"] = temp;
  }
  List<string> myTextData = (List<string>) ViewState["allTextData"];
  //Loading the dynamic controls
  foreach(string data in myTextData)
  {
    AddDynamicLabel (data);
  }
}

The AddDynamicLabel() function dynamically adds a label in the placeholder.

private void AddDynamicLabel (string data)
{
    //Making the new label and giving it the appropriate value
    Label l = new Label();
    l.Text = data + "<br/>";
    //Adding the label into the page
    PlaceHolder1.Controls.Add(l);
}

And finally we have the Button1 click event handler, where we add a brand new label in our placeholder.

protected void Button1_Click(object sender, System.EventArgs e) { //Adding the new text as a label inside the placeholder AddDynamicLabel (TextBox1.Text); //Adding the new text inside the viewstate List, for retreival on subsequent postbacks List myTextData = (List) ViewState["allTextData"]; myTextData.Add(TextBox1.Text); ViewState["allTextData"] = myTextData; }

When to use the ViewState

View state is a good way to store data in between postbacks, because it doesn't take up any memory on the server side and it doesn't impose any arbitrary usage limits (such as a timeout). So, what might force you to abandon view state for another type of state management? Here are three possible reasons:

• You need to store mission-critical data that the user cannot be allowed to tamper with. (An ingenious user could modify the view state information in a postback request.) In this case, consider session state.

• You need to store information that will be used by multiple pages. In this case, consider session state, cookies, or the query string.

• You need to store an extremely large amount of information, and you don't want to slow down page transmission times. In this case, consider using a database, or possibly session state.

 

Remember, any data that you put in the view state will be part of the data stream that goes to the client and then comes back to the server, so be very careful while putting large chunks of data in the ViewState!


Tutorial toolbar:  Tell A Friend  |  Add to favorites  |  Feedback  |   Google