ASP.NET ViewState Tips and Tricks #2
- by João Angelo
If you need to store complex types in ViewState DO implement IStateManager to control view state persistence and reduce its size. By default a serializable object will be fully stored in view state using BinaryFormatter.
A quick comparison for a complex type with two integers and one string property produces the following results measured using ASP.NET tracing:
BinaryFormatter: 328 bytes in view state
IStateManager: 28 bytes in view state
BinaryFormatter sample code:
// DO NOT
[Serializable]
public class Info
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}
public class ExampleControl : WebControl
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!this.Page.IsPostBack)
        {
            this.User = new Info { Id = 1, Name = "John Doe", Age = 27 };
        }
    }
    public Info User
    {
        get
        {
            object o = this.ViewState["Example_User"];
            if (o == null)
                return null;
            return (Info)o;
        }
        set { this.ViewState["Example_User"] = value; }
    }
}
IStateManager sample code:
// DO
public class Info : IStateManager
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    private bool isTrackingViewState;
    bool IStateManager.IsTrackingViewState
    {
        get { return this.isTrackingViewState; }
    }
    void IStateManager.LoadViewState(object state)
    {
        var triplet = (Triplet)state;
        this.Id = (int)triplet.First;
        this.Name = (string)triplet.Second;
        this.Age = (int)triplet.Third;
    }
    object IStateManager.SaveViewState()
    {
        return new Triplet(this.Id, this.Name, this.Age);
    }
    void IStateManager.TrackViewState()
    {
        this.isTrackingViewState = true;
    }
}
public class ExampleControl : WebControl
{
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        if (!this.Page.IsPostBack)
        {
            this.User = new Info { Id = 1, Name = "John Doe", Age = 27 };
        }
    }
    public Info User { get; set; }
    protected override object SaveViewState()
    {
        return new Pair(
            ((IStateManager)this.User).SaveViewState(),
            base.SaveViewState());
    }
    protected override void LoadViewState(object savedState)
    {
        if (savedState != null)
        {
            var pair = (Pair)savedState;
            this.User = new Info();
            ((IStateManager)this.User).LoadViewState(pair.First);
            base.LoadViewState(pair.Second);
        }
    }
}