While working on one project it happend that Ajax PostBack lasted longer than page reload. Since UpdatePanels were optimized, I guessed that ViewState was too big – and I was right. ViewState was more than 200KB!!!
What was the problem?
The page had a few controls used for filtering results, and the results were displayed in a user controls with repeaters. There was too much data in the ViewState. Perfect for killing performance.
How the problem was solved?
The solution to the problem is hidden in the explanation of ViewState itself. Let’s see how it functions and how it can make your day miserable.
So, what ViewState is?
ViewState represents a state of the page when it was last time processed on the server. It preserves the state of the page during PostBack operation, and by default is a part of a page. That means that it travels to and from the server along with the page. Keep in mind that some controls will preserve their values during PostBack even without ViewState.
The code below shows typical example of ViewState that can bee seen in the page source.
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE"
value="/wEPDwUJODk3NTAwMDY5D2QWAgICD2QWAmYP=" />
ViewState value is Base64 encoded text. So, it is NOT encrypted like many developers think, but rather encoded. ViewState is managed by StateBag class that is familiar with Dictionary class. It holds Key-Value pairs, and by reading this collection ViewState mecnahism preserves controls values on the page during PostBack.
Since ViewState is part of a page it is easy to access and use, but at the same time it is a silent “performance killer”. It is so easy to get carried away and store everything in ViewState. That’s why I’ll show you two, more or less known solutions for ViewState optimization.
First solution: Disabling ViewState
ViewState is enabled for all server controls by default, unless we do something. But we are going to do something, because we don’t want to have a ViewState of 200KB! It can be disabled on application level, page level, or it can be disabled for each control. The first solution could be very dangerous, and it highly unlikely you’ll ever use it.
Disabling ViewState at the page level is reasonable only for read-only pages – the ones that will never be posted back, but rathar just rendering some results. Disabling can be done just by setting EnableViewState property of a Page directive to false.
<%@ Page Language="C#" EnableViewState="false" %>
Disabling ViewState at control level is more attractive. You can disable ViewState for each server control by setting the EnableViewState property of a control.
GridView1.EnableViewState = false;
But be careful! Controls like GridView will lose the most of its functionality if ViewState is disabled. That means that you’ll disable ViewState for GridView controls that just render the data. This applies to other controls as well.
However, except on the client, ViewState can be stored in a different location, such as database. This requires a new approach to the ViewState optimization.
Second solution: Storing ViewState on the server
To store ViewState on the server, we’ll have to use two virtual methods exposed by Page class.
protected virtual
void SavePageStateToPersistenceMedium(object viewState);
protected virtual
object LoadPageStateFromPersistenceMedium();
We can implemet our own storing mechanism by overriding those two methods. This means that ViewState will no longer be a part of a page, but rathar sotored on the server.
protected override void
SavePageStateToPersistenceMedium(object ViewState)
{
StringBuilder sb = new StringBuilder();
StringWriter swr = new StringWriter(sb);
LosFormatter formatter = new LosFormatter();
formatter.Serialize(swr, viewState);
swr.Close();
SampleDAO sampleDAO = new SampleDAO();
sampleDAO.SaveViewState(swr.ToString());
}
protected override object
LoadPageStateFromPersistenceMedium()
{
SampleDAO sampleDAO = new SampleDAO();
string strViewState = sampleDAO.GetViewState();
LosFormatter formatter = new LosFormatter();
object objViewState = formatter.Deserialize(strViewState);
return objViewState;
}
Before saved ViewState has to be serialized using LosFormatter class. To put it in short, LosFormatter class is used for object serialization and is optimized for serialization of string, array and hash table objects. After you serialize the string representation of a ViewState, it can be stored in the database, text file or some other location. I even found the samples of storing ViewState in the Cache or Session!
In a reverse process, during loading, you’ll have to deserialize the value from the database an return it.
How to determine the size of the ViewState and other information?
ViewState size can be calculated on the client using JavaScript, or on the server. Below are two examples that are simple and that require no explanation.
JavaScript example:
var buffer = document.forms[0]["__VIEWSTATE"].value;
document.GetElementByID("divVS").InnerHtml = buffer.length + " bytes";
C# example:
protected override void OnPreRender(EventArgs e)
{
object viewState = HttpContext.Current.Request["__VIEWSTATE"];
if (viewState == null)
HttpContext.Current.Trace.Warn("ViewState size:", "0 KB");
else
HttpContext.Current.Trace.Warn("ViewState size:",
HttpContext.Current.Request["__VIEWSTATE"].Length.ToString()
+ "KB");
base.OnPreRender(e);
}
But, can we find some other useful information about ViewState?
You can get ViewState size as well as other useful information with ViewStateAnalyzer tool. It is IE plugin that enables you to analyze local aspx pages. Exciting thing about this tool is that it can decode ViewState and show you the detailed content. You can visit ViewStateAnalyzer home page on this address: http://lab.aspitalia.com/26/ViewStateAnalyzer200.aspx#eng, or you can download it directly from here: http://lab.aspitalia.com/Ricciolo/Downloads/VSA2Setup.zip?lab=26&lang=eng.
Potential security issues with ViewState and how to avoid them
The fact that ViewState can be decoded gives the opportunity to malicious hackers to get the information from there. That means you shouldn’t store sensitive data in ViewState, such as passwords or credit card numbers. There are simple mechanisms to improve ViewState security. For more details on this, I recommend this MSDN article: How To: Configure MachineKey in ASP.NET 2.0.
Recommended readings
Understanding ViewState in ASP.NET - Joydip Kanjilal
ASP.Net Fundamentals
ViewState in ASP.NET
If you are interested in ViewState decoding I recommend this article:
ViewState: All You Wanted to Know - Paul Wilson