Persisting View State to the File System
page 4 of 7
by Justin Lovell
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 34394/ 84

My Solution to the Problem

[Download Source Code]

Scott hinted in his article of what I proposed to him - to use global unique identifiers (commonly known as GUID) to differentiate between multiple instances of the page. For those who do not know of what a GUID is, it is a randomly drawn number that is 128 bits in length. It is almost guaranteed that any GUID that is computed by the computer will be not only unique to that machine but also guaranteed that it would be unique throughout the world.

Essentially, my solution follows the simple logic of:

  1. On every page request, a GUID will automatically generate.
  2. That GUID will then be used to name the view state file.
  3. For keeping records for the next post back, the GUID is saved to a hidden field because we want to keep reference to the view state (file) which was used for that request.
  4. When post back occurs, the GUID is read from the hidden field that was assigned in step three.
  5. From there on, a new GUID is then created and the cycle repeats itself from step one until the user does not post back by moving onto another page or closing the browser window.

With the logic explained in point form above; here is my version of my view state persister. The file name is called "PersistViewStateToFileSystem2.cs" in the downloadable source. Here is the code of my version of the PersistViewStateToFileSystem class with self-explanatory comments:

public class PersistViewStateToFileSystem : Page {
   // the extension is to protect users from sniffing in on view state via a simple
   // HTTP request
   private const string FilePathFormat = "~/PersistedViewState/{0}.vs.resource";
   private const string ViewStateHiddenFieldName = "__ViewStateGuid";</font>


<font face="Verdana" size="2">   // creates a new instance of a GUID for the current request
   private Guid pViewStateFilePath = Guid.NewGuid();</font>


<font face="Verdana" size="2">   /// <summary>
   /// The path for this page's view state information (GUID based).
   /// </summary>
   public string ViewStateFilePath {
      get {
         return MapPath(String.Format(FilePathFormat, pViewStateFilePath.ToString()));
      }
   }</font>


<font face="Verdana" size="2">   /// <summary>
   /// Saves the view state to the Web server file system.
   /// </summary>
   protected override void SavePageStateToPersistenceMedium(object viewState) {
      // serialize the view state into a base-64 encoded string
      LosFormatter los = new LosFormatter();
      StringWriter writer = new StringWriter();</font>


<font face="Verdana" size="2">      // save the view state to disk
      los.Serialize(writer, viewState);
      StreamWriter sw = File.CreateText(ViewStateFilePath);
      sw.Write(writer.ToString());
      sw.Close();</font>


<font face="Verdana" size="2">      // saves the view state GUID to a hidden field
      Page.RegisterHiddenField(ViewStateHiddenFieldName, ViewStateFilePath);
   }</font>


<font face="Verdana" size="2">   /// <summary>
   /// Loads the page's view state from the Web server's file system.
   /// </summary>
   protected override object LoadPageStateFromPersistenceMedium() {
      string vsString = Request.Form[ViewStateHiddenFieldName];</font>


<font face="Verdana" size="2">      if (!File.Exists(vsString))
         throw new Exception("The Viewstate file " + vsString + " is missing!!!");
      else {
         // instantiates the formatter and opens the file
         LosFormatter los = new LosFormatter();
         StreamReader sr = File.OpenText(vsString);
         string viewStateString = sr.ReadToEnd();</font>


<font face="Verdana" size="2">         // close file and deserialize the view state
         sr.Close();
         return los.Deserialize(viewStateString);
      }
   }
}


View Entire Article

User Comments

Title: Will fail for ASP.NET 2.0   
Name: TomP
Date: 2007-12-11 9:13:31 AM
Comment:
We used this for ASP.NET 2.0 and found that you will lose your control state. A good article exists here: http://blog.arctus.co.uk/articles/2007/04/23/advanced-asp-net-storing-viewstate-in-a-database
Title: Problem with Microsoft Ajax   
Name: AnupT
Date: 2007-06-13 12:17:38 AM
Comment:
Excellent article and i was able to successfully use this in a project.

But I ran in to problem in another project that uses Microsoft Ajax 1.0.

I have a page which uses updatepanel control. In this updatepanel, i have 2 dropdownlist with autopostback enabled. For some weird reason the second dropdownlist is not maintaing the selected value. As soon as i change the 2nd dropdownlist, its value changes back to first item in the list.

This problem is happening for all the page that has 2 or more dropdownlist.
Title: Some problems occurs during long sessions   
Name: Raul
Date: 2006-01-16 12:22:06 PM
Comment:
\
Title: Httpmodule problem   
Name: Ian
Date: 2005-05-25 12:47:33 PM
Comment:
Great article.
I did run into one problem with the HttpModule. I kept getting the error "Server operation is not available in this context". I think it was because the the httpmodule is created in the Application_OnStart and at that point the context does not contain a value for Server.MapPath. Anyway, I got around this by using System.AppDomain.CurrentDomain.BaseDirectory instead.

Good stuff though
Title: Cache   
Name: Wesley
Date: 2004-08-07 5:58:02 AM
Comment:
Justin,

I thought it was all about minimizing site traffic due to the sometimes very large viewstate. Just a little misunderstanding. But...

Your mathwork showed me somthing else as wel. 50 x 8 x 15 = 6000KB an hour! If we're talking about shared hosting most hosts give you a harddisk space of 50MB to 100MB which means that in the best case(not counting object allready there) we got 16.6 hours of viewstate left. So it's not very usefull for the average.

I would like to thank you both(scott and you) an awfull lot for explaning viewstate in such an extended way. I managed to solve my viewstate problems on the composite control mentioned in the url.

Cheers,

Wes
Title: Postback problem still exists   
Name: Justin Lovell
Date: 2004-08-07 5:57:14 AM
Comment:
Richard,

As I have already said to, the problem that you are experiencing is due to the fact that my HTML code that I posted is directing you to Scott's example page.

I have upload the new source code with the fixed HTML
Title: re: Cache   
Name: Justin Lovell
Date: 2004-08-06 5:43:53 PM
Comment:
Hi Wesley,

You can use the cache object to store the view state. However, it totally depends on what type of site you are running. The main issue that was addressed by persisting the view state to the file system is that an user can fill a form and then leave it to stand over night before he submits his changes.

If you are using the cache object, you will then have to counter that time-restriction by placing the cache time to a couple of hours and sometimes as long as a day. If your site gets an average of 50 users who all visit eight pages on average, and assuming that the average view state size is 15KB, then do the maths: 50 x 8 x 15 = 6000KB of memory (~6MB). That is a low traffic site... now let's multiply the amount of sites doing exactly that (shared hosting for low traffic sites) to about 40: that is ~240MG just for just holding view state into memory.

That is a bit inefficient. However, it becomes even more dramatized if you have to run off medium trafic site. And to make it worst: you can't scale your application to a web farm.

It is all about keeping your options open... and your memory for better use :-)
Title: Cache   
Name: Wesley
Date: 2004-08-06 2:57:28 PM
Comment:
As I am quit new on programming in .Net I tend to read a lot just to learn. So don't blame me if this is a stupid idea

One thing I truly don't understand: Why not cache the viewstate by the name of the SessionID+Page and the time a session exists? Something like: cache.insert(SessionId+Page, Viewstate,,DateTime.Now.AddMinutes(SessionTTL))

In that case your sure to get the viewstate corresponding to the current session, it auto cleans up the mess and it's a lot quicker I guess... You just have to make sure the cache isn't cleared.

Cheers,
Wes
Title: Postback problem still exists   
Name: Richard Lemmon
Date: 2004-08-06 2:41:38 PM
Comment:
I followed your article and was able to duplicate the same error that was being caused by Scott's code.

Try the following:

1.) http://localhost/ViewStateToFS/MySolution.aspx
2.) Click on the "Show User Control A"
3.) Select Hello world
4.) right-click on "Show user Control B" and select Open in new window
5.) In the new window click Postback
6.) Return to the initial window & click Postback

same error.

Regards,

Rich Lemmon
rich@lindenstreet.com
Title: A couple of very small points on an otherwise excellent article   
Name: Scott Galloway
Date: 2004-08-06 11:37:13 AM
Comment:
Great article, I do have a couple of small points though - firstly, as written your code writes the filepath into the HTML source of the generated page; this is not really a great idea as path disclosure is generally to be avoided in web apps. I made a simple modification to allow just the GUID portion to be stored in the hidden field - which is also smaller :-). Second point is to do with the HttpModule you use for cleanup, I tend to use a different approach here, using a Timer object stored as a static object - it has the nice side effect of avoiding using a separate module but it does have the disadvantage of requiring a code change.

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-10-23 7:19:07 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search