This week I have been working with a customer that had pretty large ViewStates that were getting pushed up and down between the client and the server.  The application was moving about 200+ KB of ViewState between the client and server.  This is something we picked out quickly as a scale issue.

Now Tess has a great blog on why this is a problem from a memory perspective and provides some background on the issue:

ASP.NET Memory – Identifying pages with high ViewState
http://blogs.msdn.com/tess/archive/2008/09/09/asp-net-memory-identifying-pages-with-high-viewstate.aspx

In this customer’s case we were seeing multisecond times for downloading a page from the server and sending the response back to the server so this was also having an impact on performance even before it because a memory problem.  They would run into the memory issues also once load is ramped up.

The customer posed the question - “Well how do I know what is in my ViewState and what is causing the bloat?”

This is a fair question and we referred to Tess’s blog but hit some snags that I wanted to comment on incase other people hit these. (read her blog first for background if you have questions)

Where is the ViewState? 

To get started we downloaded ViewState Decoder (2.2) but we could not point it directly at the page due to permissions issues. Therefore we went to pull the ViewState from the “View Source” of the page when viewing in IE.  A problem arose because as we navigated the page we would see the page sizes increase in the IIS logs (SC-BYTES value) but the page remained the same size when we did “View Source”.  Basically if we saved the “View Source” that page was identical even though a number of postbacks had occurred.  When I opened the IIS Log I saw each request and the log reported that SC-BYTES (Bytes Sent) was increasing (almost double the initial page request) so something was not adding up.

In this application it has one page with multiple tabs and as we move through the tabs the page grows but as we said that was not reflected in the “View Source.”  It turns out after talking with the customer that they are using the Updater Panel from the AJAX toolkit and each of the postbacks is an update to that panel.  These updates are not reflected in the “View Source.” To capture this easily we returned to an old favorite – Fiddler from http://www.fiddlertool.com/fiddler/

From there we were able to get the ViewState out.  Because this was being sent back to AJAX the ViewState showed up like this:

|hiddenField|__VIEWSTATE|/wE
<CLIP>
EA==|9168|hiddenField|__VIEWSTATEENCRYPTED  

You will notice that these are not normal tags.  Basically the ViewState continued between the “|”.  We grabbed this but and dropped it into the ViewState Decoder but got an error that the ViewState was invalid:

There was an error decoding the ViewState string: The serialized data is invalid

Why is the ViewState string invalid if it worked?

We puzzled over this for a bit and then I noticed what you may already have noticed in the list of hidden fields:

__VIEWSTATEENCRYPTED

It turns out that this indicates that the ViewState is encrypted.  So it was understandable that the tool could not easily decode this via my cut and paste of the ViewState.  We decided to turn off ViewStateEncryption for this troubleshooting since the application was just in test.  Basically we add ViewStateEncryptionMode=”none” for this test to Page Directive on the page.  Then BINGO!  We were able to decode the ViewState and get some rich information.

Here are some links on encryption:

@ Page Directive
http://msdn.microsoft.com/en-us/library/ydy4x04a.aspx

ViewStateEncryptionMode
http://msdn.microsoft.com/en-us/library/system.web.ui.viewstateencryptionmode.aspx

For ViewStateEncryptionMode the default is auto which means if any of your control request encryption using the following API ViewState will get encrypted:

RegisterViewStateEncryption 
http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerrequiresviewstateencryption.aspx

All That Data, There Must be an Easier Way!

Now as we scrolled through all of the data in the output we could see what is stored in the ViewState but tying back to a particular control is not simple.  Also, since there was so much stored in this ViewState it was impossible to easily know what controls were the worst offenders.  So we moved to one last place – Builtin ASP.NET tracing.  We enabled the tracing because there is a VERY helpful column that gets produced - ViewState Size bytes.  This is done for each control that is rendered and makes short order of what controls are the worst offenders.  You will get output like this:

Control ID

Type

Render Size bytes

ViewState Size bytes

ControlState Size bytes

Control1

System.Web.UI.WebControls.DropDownList

0

1084

0

Control2

System.Web.UI.WebControls.DropDownList

0

1084

0

Control3

System.Web.UI.WebControls.DropDownList

0

1084

0

So there we had it!  Control names and their ViewState Size.  We were able to quickly look at who the worst offenders are and start removing the unneeded stuff and fixing the application.

Reading ASP.NET Trace Information
http://msdn.microsoft.com/en-us/library/kthye016(VS.80).aspx

I hope this adds some additional information this discussion of troubleshooting ViewState.

Have a great day!

Zach