Attention: We are retiring the ASP.NET Community Blogs. Learn more >

Storing ViewState in SQL

The new adapter architecture of ASP.NET v2.0 allows you to do some amazing things, We'll use this new feature to store viewstate in sql.

Firstly you must add the special folder App_Browsers to your project, then create a new .browser file and add the following

<browsers>

  <browser refID="Default">

    <controlAdapters>

      <adapter

          controlType="System.Web.UI.Page"

          adapterType="Sample.Web.UI.SqlPageAdapter" />

    </controlAdapters>

  </browser>

</browsers>


by doing this we are telling the runtime to use Sample.Web.UI.SqlPageAdapter instead of the default System.Web.UI.Page

Then we create a new class called SqlPageAdapter that inerits from PageAdapter and override the GetStatePersister method, by default PageAdapter returns PageStatePersister, we will return our own class (SqlPageStatePersister).

namespace Sample.Web.UI

{

    public class SqlPageAdapter : PageAdapter

    {

        public override PageStatePersister GetStatePersister()

        {

            return new SqlPageStatePersister(Page);

        }

    }

}


in our SqlPageStatePersister class we override the Load and Save methods. In ASP.NET v1.1 we only had to worry about viewstate, but now there is control state, so we need to serialize/deserialize both, we can do this by using the StateFormatter.

IStateFormatter isf = this.StateFormatter;

Pair p = new Pair(this.ViewState, this.ControlState);

string encoded = isf.Serialize(p);


encoded is a Base64 encoded string.

Next we need a key that saves/loads viewstate on each postback. To do this we can store a uniqueidentifier in a hidden field on the page.

private Guid GetViewStateKey()

{

    string key = this.Page.Request.Form["__VIEWSTATEGUID"];

    if (string.IsNullOrEmpty(key) || key.Length < 1)

    {

        return new Guid();

    }

    try

    {

        return new Guid(key);

    }

    catch (FormatException)

    {

        return new Guid();

    }
}


Then on the save method we check if the hidden field exists on the page, if not we add it to the page using:

this.Page.ClientScript.RegisterHiddenField("__VIEWSTATEGUID", GetViewStateKey().ToString());


Now on our Load method we make another call to the GetViewStateKey() method, use this key to retrieve the base64 encoded viewstate, deserialize into a Pair then assign the Pair.First to ViewState and Pair.Second to ControlState. (we assigned ViewState to first and ControlState to second in our Save method).

IStateFormatter isf = this.StateFormatter;

Pair p = (Pair)isf.Deserialize(dr["Value"].ToString());

 

this.ViewState = p.First;

this.ControlState = p.Second;


assume dr is a SqlDataReader. Thats it!

If you have lots of controls on a page with viewstate enabled, specially datagrids this will reduce the page size considerably, but your pages will be slightly slower because you are hitting sql all the time, so do some tests and find out if viewstate on the page is better or sql is better.

Enjoy

No Comments