Reducing the page size by storing ViewState on Server



ASP.NET uses ViewState in order to maintain the value of controls during post-backs. ViewState, by default, is stored in client side. Infact, objects that are ViewState-Enabled and their state is going to be saved, are serialized and stored in a hidden field. This works fine until the size of serialized objects is not too large. If the size of objects is too large, the size of the page goes up and it means more data transfer during a round-trip. In order to reduce the page size we may use either one or two of the following methods:

  1. Compressing the page content
  2. Storing ViewState on server

In this article I am going to provide a short description on how to store ViewState on a server location. In ASP.NET 1.1 ViewState was just save inside the page but, in ASP.NET 2.0, ViewState is saved by a descendant of PageStatePersister class. This class is an abstract class for saving and loading ViewsState and there are two implemented descendants of this class in .Net Framework, named HiddenFieldPageStatePersister and SessionPageStatePersister. By default HiddenFieldPageStatePersister is used to save/load ViewState information, but we can easily get the SessionPageStatePersister to work and save ViewState in Session object. The only thing to do this is to override PageStatePersister property of Page class and ask it to return an instance of SessionPageStatePersister class:

protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(Page);
}
}

Let’s create a small website and see what happens if we make this change. In the attached sample website, I have created a class named Person, having two string properties named First Name and LastName. Then a list of 10,000 Person object is created, added to ViewState, and displayed with a GridView control:

if (!IsPostBack)
{
List<Person> PersonList = new List<Person>();
for (int i = 0; i < 1000; i++)
{
PersonList.Add(new Person { FirstName = “Aref”, LastName = “Karimi” });
}
ViewState.Add(“PersonList”, PersonList);
GridView1.DataSource = PersonList;
GridView1.DataBind();
}

The size of Default.aspx page in this state is 165,952 bytes.

If I override PageStatePersister property of the page, with the code bellow, the size of the page will be 80,152 bytes, nearly half of the previous page size!

protected override PageStatePersister PageStatePersister
{
get
{
return new SessionPageStatePersister(Page);
}
}

Please note that Session State is, by default, stored in-process and consumes memory. Therefore, this approach is good for the websites with few or medium visitors. If the size of Session object goes beyond the server memory, your application will crash.

A solution for this problem is to persist Session State on Sql Server. This is possible only if, all the objects stored in Session are serialize able. For example, if for any reason, a SqlConnection is stored in Session object, you can not persist it in SQL Server . Furthermore, in many cases, we want to persist ViewState only and not the complete Session content.

A better solution is to write our custom persister class by deriving a new class from PageStatePersister class. In the new persister class we may store/retrieve the ViewState in any medium, like a file or Sql Server. PageStatePersister is an abstract class with two abstract methods named Save and Load. Save, stores ViewState and Load, retrieves it.

Before saving and loading the session object, we must notice that the state of each individual page must be identical. This can be reached by concatenating the SessionID and the name of the page. Moreover, a mechanism to remove all the information saved for a session, is required when a session is about to closed.

PageStatePersister provides any required information for saving and loading the ViewState. All we have to do is to Serialize and DeSerialize ViewState by PageStatePersister.StateFormatter property:

IStateFormatter formatter = this.StateFormatter;

StateFormatter, can Deserialize a serialized ViewState object and return a Pair of objects for ViewState and ControlState:

public override void Load()
{
IStateFormatter formatter = this.StateFormatter;
string VSContent = LoadFromDB(Page);
Pair statePair = (Pair)formatter.Deserialize(VSContent);
ViewState = statePair.First;
ControlState = statePair.Second;
}

In the above code, LoadFromDB is a custom method that should retrieve the serialized ViewState from database. I will not go thorough the implementation of this method because it is not necessary.

public override void Save()
{
Pair statePair = new Pair(ViewState, ControlState);
IStateFormatter formatter = this.StateFormatter;
string VSContent = formatter.Serialize(statePair);
SaveToDB(Page, VSContent);
}

The mechanism for Save method, is somehow the same. We just need to create a Pair of ViewState and ControlState properties, Serialize it and save it to the desired medium. The code above is a sample Save method.

After writing our custom PagePersister class, we need to override the Page.PageStatePersister property to return an instance of this class.

You may download the sample website from HERE.

Thanks,

Asp guy


Advertisements

5 thoughts on “Reducing the page size by storing ViewState on Server

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