Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

C# ViewState Management/Storage - Four Locations!

0.00/5 (No votes)
5 Nov 2007 2  
In this article, I discuss the PageStatePersister, and detail ViewState storage in one of four locations: Session, Application, AppGlobals, and server Cache.

Introduction

From an SEO standpoint, page size matters, as well as the location of text on your page. When creating a site with VS .Net, we end up with a ViewState variable, which in some cases, can take up a whole lot of space near the top of the page. This could, in fact, dilute the contents' importance on a given web page. In terms of page size, some search engines only cache the first 120kb of data.

This project was an attempt at finding another location to store the ViewState. In this case, I made four locations available for storage:

  • Session
  • Application
  • AppGlobals
  • Cache

This can be easily implemented in any C# project by creating a base class, referencing it in all classes, and selecting the storage location in an appSettings key in the Web.config. What is missing, however, is a SQL Server storage location. I'd be quite willing to incorporate at any such implementations!

Before fully diving into the code, I'd like to first discuss why it's important, and how the PageStatePersister, really didn't help.


Background

Enter the importance of reducing the ViewState parameter size. My initial reason for writing this code/putting it together, are a bit different that Oleg Sobol's in this (ViewStateProvider_Net2_0.asp) article, but I think are just as applicable, but our core reason is the same � ViewState size � it does matter.

Unfortunately it's been a while since I wrote this internal article, and haven't fully referenced all the sources. So if I've used some of your code, I apologize in advance.

ASP.Net ViewState Management

I tested using no ViewState management, ASP.Net 2.0's PageStatePersister, and the server caching method.

My overall results show that the server caching method is superior to the others. In some cases, the payload of the PageStatePersister is about equal to that of the server cache method, but on pages that contain a higher number of server controls, the PageStatePersister falls dramatically short of the server cache method (see Login.aspx below).

Server caching offers four ViewState stores - session, application, appglobals, cache. For testing purposes I only used server caching, as the data below reflects it is the superior method.

It is my conclusion, based on this and the benchmark tests located at http://www.eggheadcafe.com/articles/20040613.asp, that we use the server cache method.

ViewState test without the server-side scheme is in the first column; the four server side schemes follow:

VIEWSTATE WEB STRESS COMPARISON

TEST NAME

VIEWSTATE

SESSION

APPLICATION

CACHE

GLOBALS

NUMBER OF HITS

3322

18483

18476

20170

16723

REQUESTS /SEC

27.64

153.8

153.74

167.84

140.32

TOTAL BYTES REC'D (KB)

68016.63

22923.25

22977.13

25074.51

20798

PERCENT DIFFERENCE

N/A

456.44%

456.22%

507.24%

407.67%

Regarding the server stores method, I've used the same design pattern myself � first routing data through a base class � very slick.

I've created an assembly containing the ViewState handler, which I can import into any future projects that use these classes. Once again � write once, use anywhere. I also converted some of the code for better usability with 2.0.

Test results below:

Default01.aspx

No Viewstate Management: ~ 329 characters | Payload: 1k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTExMjY5MTM5MTYPZBYCAgMPZBYCAgsPZBYCAgEPFgIeC18h
SXRlbUNvdW50AgUWCmYPZBYCZg8VAQdBZHZhbnRhZAIBD2QWAmYPFQEQQW
1lcmljYW4gRXhwcmVzc2QCAg9kFgJmDxUBCUJBTktGSVJTVGQCAw9kFgJmDxUB
BUNoYXNlZAIED2QWAmYPFQEXQ29sdW1idXMgQmFuayBhbmQgVHJ1c3RkZHE/U
FRpXKP0LBuXCsdD3lver4Y3" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTExMjY5MTM5MTYPZBYCAgMPZBYCAgsPZBYCAgEPFgIeC18h
SXRlbUNvdW50AgUWCmYPZBYCZg8VAQdBZHZhbnRhZAIBD2QWAmYPFQEQQW
1lcmljYW4gRXhwcmVzc2QCAg9kFgJmDxUBCUJBTktGSVJTVGQCAw9kFgJmDxUB
BUNoYXNlZAIED2QWAmYPFQEXQ29sdW1idXMgQmFuayBhbmQgVHJ1c3RkZHE/U
FRpXKP0LBuXCsdD3lver4Y3" />

PageStatePersister: ~ 129 characters | Payload: < 1k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWE3YzI3MGY1OGRg4WBM0VRZaUOeHh7vqbaRwGRdYA==" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWMyNTU5MGZlZWSRqIAAKVQl2MXv4b2MnOhsDZhOJA==" />

Server Cache Viewstate Storage: ~ 140 characters | Payload: < 1k

<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="4" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />

<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="9" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />

No Viewstate Management: ~ 349 characters | Payload: ~ 1k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMzE0MTExNjQyD2QWAgIDD2QWAgIED2QWAgIBDxYCHgtfIUl0ZW
1Db3VudAIFFgpmD2QWAmYPFQEHQWR2YW50YWQCAQ9kFgJmDxUBEEFtZXJpY
2FuIEV4cHJlc3NkAgIPZBYCZg8VAQlCQU5LRklSU1RkAgMPZBYCZg8VAQVDaGFzZWQ
CBA9kFgJmDxUBF0NvbHVtYnVzIEJhbmsgYW5kIFRydXN0ZBgBBQlHcmlkVmlldzEPZ2R
mesVnAmycBPQuwY/+R2iSTw8AgA==" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMzE0MTExNjQyD2QWAgIDD2QWAgIED2QWAgIBDxYCHgtfIUl0ZW1
Db3VudAIFFgpmD2QWAmYPFQEHQWR2YW50YWQCAQ9kFgJmDxUBEEFtZXJpY2F
uIEV4cHJlc3NkAgIPZBYCZg8VAQlCQU5LRklSU1RkAgMPZBYCZg8VAQVDaGFzZWQCB
A9kFgJmDxUBF0NvbHVtYnVzIEJhbmsgYW5kIFRydXN0ZBgBBQlHcmlkVmlldzEPZ2Rme
sVnAmycBPQuwY/+R2iSTw8AgA==" />

PageStatePersister: ~ 149 characters | Payload: < 1k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWQ1YTljYjg0NBgBBQlHcmlkVmlldzEPZ2S3+UlLsRyU8KTbI
sZjQZTqo3Eh2Q==" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWQ2MzI3MDRhNhgBBQlHcmlkVmlldzEPZ2R0CWKRyWY
H15G9LmpwwFnocxQkxQ==" />

Server Cache Viewstate Storage: ~ 141 characters | Payload: < 1k

<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="11" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />

Login.aspx

No Viewstate Management: ~ 1345 characters | Payload: ~ 2k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM3MDg0NzE3NWQYAwUeX19Db250cm9sc1JlcXVpcmVQb3N0QmF
ja0tleV9fFg0FEUxvZ2luMSRSZW1lbWJlck1lBRdMb2dpbjEkTG9naW5JbWFnZUJ1dHRvbg
U8Q3JlYXRlVXNlcldpemFyZDEkX19DdXN0b21OYXYwJFN0ZXBQcmV2aW91c0J1dHRvbk
ltYWdlQnV0dG9uBThDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3RvbU5hdjAkU3RlcE5leHRCd
XR0b25JbWFnZUJ1dHRvbgU2Q3JlYXRlVXNlcldpemFyZDEkX19DdXN0b21OYXYwJENhbm
NlbEJ1dHRvbkltYWdlQnV0dG9uBUlDcmVhdGVVc2VyV2l6YXJkMSRTdGFydE5hdmlnYXRp
b25UZW1wbGF0ZUNvbnRhaW5lcklEJFN0YXJ0TmV4dEltYWdlQnV0dG9uBUZDcmVhdGVV
c2VyV2l6YXJkMSRTdGFydE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJENhbmNlb
EltYWdlQnV0dG9uBU9DcmVhdGVVc2VyV2l6YXJkMSRGaW5pc2hOYXZpZ2F0aW9uVGVtc
GxhdGVDb250YWluZXJJRCRGaW5pc2hQcmV2aW91c0ltYWdlQnV0dG9uBUdDcmVhdGVV
c2VyV2l6YXJkMSRGaW5pc2hOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRGaW5p
c2hJbWFnZUJ1dHRvbgVHQ3JlYXRlVXNlcldpemFyZDEkRmluaXNoTmF2aWdhdGlvblRlbXBs
YXRlQ29udGFpbmVySUQkQ2FuY2VsSW1hZ2VCdXR0b24FS0NyZWF0ZVVzZXJXaXphcmQx
JFN0ZXBOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRTdGVwUHJldmlvdXNJbWFnZ
UJ1dHRvbgVHQ3JlYXRlVXNlcldpemFyZDEkU3RlcE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRh
aW5lcklEJFN0ZXBOZXh0SW1hZ2VCdXR0b24FRUNyZWF0ZVVzZXJXaXphcmQxJFN0ZXBOY
XZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRDYW5jZWxJbWFnZUJ1dHRvbgURQ3JlY
XRlVXNlcldpemFyZDEPEGQUKwABZmZkBSFDcmVhdGVVc2VyV2l6YXJkMSRXaXphcmRN
dWx0aVZpZXcPD2RmZIG8LAAmxd9A5eBGBmrtERp+z8nr" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKLTM3MDg0NzE3NWQYAwUeX19Db250cm9sc1JlcXVpcmVQb3N0QmF
ja0tleV9fFg0FEUxvZ2luMSRSZW1lbWJlck1lBRdMb2dpbjEkTG9naW5JbWFnZUJ1dHRvbg
U8Q3JlYXRlVXNlcldpemFyZDEkX19DdXN0b21OYXYwJFN0ZXBQcmV2aW91c0J1dHRvbkl
tYWdlQnV0dG9uBThDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3RvbU5hdjAkU3RlcE5leHRCd
XR0b25JbWFnZUJ1dHRvbgU2Q3JlYXRlVXNlcldpemFyZDEkX19DdXN0b21OYXYwJENhb
mNlbEJ1dHRvbkltYWdlQnV0dG9uBUlDcmVhdGVVc2VyV2l6YXJkMSRTdGFydE5hdmlnYX
Rpb25UZW1wbGF0ZUNvbnRhaW5lcklEJFN0YXJ0TmV4dEltYWdlQnV0dG9uBUZDcmVhd
GVVc2VyV2l6YXJkMSRTdGFydE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJENhb
mNlbEltYWdlQnV0dG9uBU9DcmVhdGVVc2VyV2l6YXJkMSRGaW5pc2hOYXZpZ2F0aW9u
VGVtcGxhdGVDb250YWluZXJJRCRGaW5pc2hQcmV2aW91c0ltYWdlQnV0dG9uBUdDc
mVhdGVVc2VyV2l6YXJkMSRGaW5pc2hOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJ
JRCRGaW5pc2hJbWFnZUJ1dHRvbgVHQ3JlYXRlVXNlcldpemFyZDEkRmluaXNoTmF2aWd
hdGlvblRlbXBsYXRlQ29udGFpbmVySUQkQ2FuY2VsSW1hZ2VCdXR0b24FS0NyZWF0ZVV
zZXJXaXphcmQxJFN0ZXBOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRTdGVwU
HJldmlvdXNJbWFnZUJ1dHRvbgVHQ3JlYXRlVXNlcldpemFyZDEkU3RlcE5hdmlnYXRpb25U
ZW1wbGF0ZUNvbnRhaW5lcklEJFN0ZXBOZXh0SW1hZ2VCdXR0b24FRUNyZWF0ZVVzZX
JXaXphcmQxJFN0ZXBOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRDYW5jZWxJ
bWFnZUJ1dHRvbgURQ3JlYXRlVXNlcldpemFyZDEPEGQUKwABZmZkBSFDcmVhdGVVc
2VyV2l6YXJkMSRXaXphcmRNdWx0aVZpZXcPD2RmZIG8LAAmxd9A5eBGBmrtERp+z8nr" />

PageStatePersister: ~ 1353 characters | Payload: ~ 2k

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWI2ODhhNzZiNBgDBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3
RCYWNrS2V5X18WDQURTG9naW4xJFJlbWVtYmVyTWUFF0xvZ2luMSRMb2dpbkltYWdl
QnV0dG9uBTxDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3RvbU5hdjAkU3RlcFByZXZpb3VzQ
nV0dG9uSW1hZ2VCdXR0b24FOENyZWF0ZVVzZXJXaXphcmQxJF9fQ3VzdG9tTmF2MCR
TdGVwTmV4dEJ1dHRvbkltYWdlQnV0dG9uBTZDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3Rvb
U5hdjAkQ2FuY2VsQnV0dG9uSW1hZ2VCdXR0b24FSUNyZWF0ZVVzZXJXaXphcmQxJFN0Y
XJ0TmF2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkU3RhcnROZXh0SW1hZ2VCdXR0
b24FRkNyZWF0ZVVzZXJXaXphcmQxJFN0YXJ0TmF2aWdhdGlvblRlbXBsYXRlQ29udGFpb
mVySUQkQ2FuY2VsSW1hZ2VCdXR0b24FT0NyZWF0ZVVzZXJXaXphcmQxJEZpbmlzaE5h
dmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJEZpbmlzaFByZXZpb3VzSW1hZ2VCdXR0
b24FR0NyZWF0ZVVzZXJXaXphcmQxJEZpbmlzaE5hdmlnYXRpb25UZW1wbGF0ZUNvbnR
haW5lcklEJEZpbmlzaEltYWdlQnV0dG9uBUdDcmVhdGVVc2VyV2l6YXJkMSRGaW5pc2hOY
XZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRDYW5jZWxJbWFnZUJ1dHRvbgVLQ3JlY
XRlVXNlcldpemFyZDEkU3RlcE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJFN0ZXBQ
cmV2aW91c0ltYWdlQnV0dG9uBUdDcmVhdGVVc2VyV2l6YXJkMSRTdGVwTmF2aWdhdGlvb
lRlbXBsYXRlQ29udGFpbmVySUQkU3RlcE5leHRJbWFnZUJ1dHRvbgVFQ3JlYXRlVXNlcldpem
FyZDEkU3RlcE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJENhbmNlbEltYWdlQnV0d
G9uBRFDcmVhdGVVc2VyV2l6YXJkMQ8QZBQrAAFmZmQFIUNyZWF0ZVVzZXJXaXphcmQ
xJFdpemFyZE11bHRpVmlldw8PZGZkplxAEGixaZpDZjFXu/FEiNL4p5U=" />

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhjODNlOWJiMTBiNTk5ZRgDBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RC
YWNrS2V5X18WDQURTG9naW4xJFJlbWVtYmVyTWUFF0xvZ2luMSRMb2dpbkltYWdlQnV
0dG9uBTxDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3RvbU5hdjAkU3RlcFByZXZpb3VzQnV0d
G9uSW1hZ2VCdXR0b24FOENyZWF0ZVVzZXJXaXphcmQxJF9fQ3VzdG9tTmF2MCRTdG
VwTmV4dEJ1dHRvbkltYWdlQnV0dG9uBTZDcmVhdGVVc2VyV2l6YXJkMSRfX0N1c3RvbU
5hdjAkQ2FuY2VsQnV0dG9uSW1hZ2VCdXR0b24FSUNyZWF0ZVVzZXJXaXphcmQxJFN0Y
XJ0TmF2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkU3RhcnROZXh0SW1hZ2VCdXR0
b24FRkNyZWF0ZVVzZXJXaXphcmQxJFN0YXJ0TmF2aWdhdGlvblRlbXBsYXRlQ29udGFp
bmVySUQkQ2FuY2VsSW1hZ2VCdXR0b24FT0NyZWF0ZVVzZXJXaXphcmQxJEZpbmlzaE
5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJEZpbmlzaFByZXZpb3VzSW1hZ2VCdX
R0b24FR0NyZWF0ZVVzZXJXaXphcmQxJEZpbmlzaE5hdmlnYXRpb25UZW1wbGF0ZUNvb
nRhaW5lcklEJEZpbmlzaEltYWdlQnV0dG9uBUdDcmVhdGVVc2VyV2l6YXJkMSRGaW5pc2
hOYXZpZ2F0aW9uVGVtcGxhdGVDb250YWluZXJJRCRDYW5jZWxJbWFnZUJ1dHRvbgV
LQ3JlYXRlVXNlcldpemFyZDEkU3RlcE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJF
N0ZXBQcmV2aW91c0ltYWdlQnV0dG9uBUdDcmVhdGVVc2VyV2l6YXJkMSRTdGVwTmF
2aWdhdGlvblRlbXBsYXRlQ29udGFpbmVySUQkU3RlcE5leHRJbWFnZUJ1dHRvbgVFQ3Jl
YXRlVXNlcldpemFyZDEkU3RlcE5hdmlnYXRpb25UZW1wbGF0ZUNvbnRhaW5lcklEJENhb
mNlbEltYWdlQnV0dG9uBRFDcmVhdGVVc2VyV2l6YXJkMQ8QZBQrAAFmZmQFIUNyZWF
0ZVVzZXJXaXphcmQxJFdpemFyZE11bHRpVmlldw8PZGZk1a3F/q3nBJJ0+8canPDJgQV
8YLE=" />

Server Cache Viewstate Storage: ~ 141 characters | Payload: < 1k

<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="1" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />

<input type="hidden" name="__VIEWSTATE1" id="__VIEWSTATE1" value="2" />
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="" />

Managing the ViewState

The solution is to create a base class to manage the Viewstate.

Create an Assembly called StaticAppGlobals where three files will reside:

  • AppGlobal.cs
  • BasePage.cs (this is your base class that will be inherited in all classes)
  • viewStateSvrMgr.cs

Setting the ViewState Storage Location

We can select to store the ViewState in one of several locations:

  • Session
  • Application
  • Appglobals
  • Cache

Selection of the receptacle is done in the web-app's Web.config file:

<appSettings>
    <add key="ServerSideViewState" value="true"/>
    <!--ViewStateStore: session|application|appglobals|cache-->
    <add key="ViewStateStore" value="cache"/>
</appSettings>

Using the Base Class

Since each class needs to inherit System.Web.UI.Page we will inherit this from our base class, and inherit our base class in all classes:

Instead of :

public partial class Default : System.Web.UI.Page
{
    ... 
}

The definition of our class now becomes:

using StaticAppGlobals;  // viewstate management uses BasePage

public partial class Default : BasePage
{
    ... 
}

Now, since all pages must inherit Page, the base class inherits this:

namespace StaticAppGlobals
{
    public class BasePage : System.Web.UI.Page
    {
        ...
    }
    
    ...
}
... and now, you're off to the races, with C# ViewState management!

Points of Interest

While using the Server Cache method on a heavily-visited site without proper cache management, a server crash can be experienced, so the other methods would be preferable.

I haven't had a chance to work on a SQL implementation, but would love to see one added to this.

I've added this to several projects I've created. One, gave administrators the options to select the storage location from a radio button list. Thus, no re-compiling and the change was instant.

History

None yet...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here