ViewState is useful for saving a control's state across page post backs, but is does no good at all if you are navigating via links...the ViewState is only ever used during a POST not a GET. If you have a SharePoint publishing site (or even a collaboration site) then the majority of navigation will be via links in the content and not post backs. This makes a vast amount of the ViewState redundant and so can safely be removed.
By default ASP.Net controls have their ViewState on and so is the case with SharePoint controls...this leads to an ever growing ViewState in the page, which I have seen over 20k in size.
Its always worthwhile trying to reduce the footprint of your ViewState as it makes the pages load faster on the client and reduces the processing on the server. Fortunately there is an easy way to see where the ViewState is produced and to check if your efforts have reduced it.
Page Trace
By far the easiest way to see what is creating your pages ViewState is to turn page tracing on in web.config...
Once this is on then you can use trace.axd to see the trace output from the page request. If you are doing this remotely from the server then you will need to add the attribute localOnly=false. You could also set pageOutput=true so that you don't need to access trace.axd and get the required information directly in the requested page.
The page trace output contains a section called 'Control Tree' and this section can be used to see the size of your ViewState and the controls which are producing it...
Here you see the two SharePoint menu controls are producing 384 & 280 bytes of ViewState . Generally this ViewState will not be used for anything and just takes time to build on the server, send to the client and for the client to parse.
The above trace output shows the ViewState created by the default page of the 'Press Releases' subsite in a standard MOSS publishing site. This template has only one subsite and so has very little navigation. Below is the output for the same page when only a further five subsites are added...
As you can see the ViewState has increased by 512 bytes and will continue to increase the more sites, pages or subsites are included in the navigation. As this is a SharePoint website there are going to be very few postbacks which will utilize this ViewState and so removing it will improve the performance.
Modifying the master page
In order to remove the ViewState we need to change the master page, in my case the BlueBand.master. You will need to find all the <SharePoint:AspMenu> controls and add a parameter of EnableViewState=False...
This is the left navigation ViewState before turning the ViewState off...
And after...
That's 952 bytes of ViewState saved and that's with only six items in the navigation. Many have over 30 items and could be saving over 5k of ViewState in each request. By turning off the view state for all AspMenu controls will save a fair bit of overhead in the weight of the page.
Using the BlueBand master page on the 'Press Releases' home page will generate 3,156 bytes of ViewState, by disabling the ViewState for the three navigation controls in the master page this will be reduced to 2,320 bytes. By disabling the SiteActions ViewState it will be reduced to 2,088 bytes and finally by disabling it on the Welcome ascx it will be reduced to 1,412 bytes. This is less than half the original.
Going further with some development
Other ViewState culprits in SharePoint are the Field Controls, these generate ViewState even if they are only displaying HTML and not allowing authoring...
The image above shows the FieldValue control, which only ever displays the content of a field...its still using ViewState and 224 bytes at that. This happens to be the Page Title in the header and so to display 20 bytes for the text of the title the client is actually having to download 244 bytes...All field controls appear to produce at least 224 bytes of ViewState.
The main problem with SharePoint field controls is that they actually rely on the ViewState during editing and so you cannot just disable it...they will stop working when you edit the page. However we can use the fact that whether ViewState is enabled or not is inherited from the controls parent. Using this fact we can selectively disable the ViewState when the page is just being displayed.
By creating a container control we can control the ViewState of the controls it contains...
public class ViewStatePanel : Control
{
protected override void OnInit(EventArgs e)
{
if (SPContext.Current.FormContext.FormMode == Microsoft.SharePoint.WebControls.SPControlMode.Display)
EnableViewState = false;
base.OnInit(e);
}
protected override void Render(HtmlTextWriter writer)
{
RenderChildren(writer);
}
}
This control can then be used to 'wrap' the offending SharePoint field controls and control their ViewState...
This will then reduce you ViewState even further. By modifying the WelcomeLinks.aspx page layout with the new container the final reduction in ViewState for an OOTB SharePoint publishing site was from an original 3,156 bytes down to 1,048 bytes...less than a third of what it was originally.
This is a fairly small reduction, but then its only a small site two pages and one subsite. You should be able to get much larger reductions using this technique in your own projects.
Try it for yourself
If you would like to try the ViewState container for yourself you can download the DLL and make the following changes.
1. Add the DLL to the GAC (or the bin folder and change trust to Full).
2. Add the following to the SafeControls in web.config
<SafeControl Assembly="TheKid.ViewState, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4e73ec0fe752cafb" Namespace="TheKid.ViewState" TypeName="*" Safe="True" />
3. Add the following line to the top of your layout page
<%@ Register Tagprefix="TheKid" Namespace="TheKid.ViewState" Assembly="TheKid.ViewState, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4e73ec0fe752cafb" %>
4. Wrap the controls for which you wish the ViewState to be controlled with <TheKid:ViewStatePanel runat="server">