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

Dynamic ViewState in ASP.NET WebForms

0.00/5 (No votes)
18 Jan 2012 1  
Implementing dynamic ViewState in ASP.NET WebForms.

If you have worked with ASP.NET MVC 3, you are probably aware of the ViewBag property which allows you to pass data from the Controller to the View by using dynamic properties instead of hard coding strings. While the properties still are not strongly typed and the compiler does not check them, it can provide an advantage. For example, you can avoid casting as it returns dynamic objects. This post will show how to use the same approach in ASP.NET Web Forms for the ViewState property giving us a dynamic viewstate class.

In order to access the properties which do not exist at compile time the class has to inherit from DynamicObject. This will allow us to override methods which are called when we get or set dynamic properties. In these methods we will use the ViewState of the current page to store and extract values.

To start with we need let’s create the DynamicViewState class and base page class which will contain the ViewBag property:

C#
public class DynamicViewState : DynamicObject
{
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        return base.TrySetMember(binder, value);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return base.TryGetMember(binder, out result);
    }
}

public class BasePage : Page
{
    private readonly dynamic viewBag;

    protected dynamic ViewBag
    {
        get { return viewBag; }
    }
}

The TryGetMember and TrySetMember methods are invoked whenever we get or set properties of ViewBag instance. This means that we should have access to ViewState of the current page so let’s pass the page to the constructor of DynamicViewState:

C#
public class DynamicViewState : DynamicObject
{
    private readonly BasePage basePage;

    public DynamicViewState(BasePage basePage)
    {
        this.basePage = basePage;
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        return base.TrySetMember(binder, value);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return base.TryGetMember(binder, out result);
    }
}

public class BasePage : Page
{
    private readonly dynamic viewBag;

    public BasePage()
    {
        viewBag = new DynamicViewState(this);
    }

    protected dynamic ViewBag
    {
        get { return viewBag; }
    }
}

We now have the page but as ViewState is protected property, we cannot access it from our methods. We could add methods for storing and retrieving items from the ViewState but that would allow all other classes to manipulate the page’s ViewState. Instead a better option is to make the DynamicViewState class nested. This way we will be able to access the ViewState property without exposing it to the outside world. The implementation of the DynamicViewState now looks like this:

C#
public class BasePage : Page
{
    private class DynamicViewState : DynamicObject
    {
        private readonly BasePage basePage;

        public DynamicViewState(BasePage basePage)
        {
            this.basePage = basePage;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            basePage.ViewState[binder.Name] = value;
            return true;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = basePage.ViewState[binder.Name];

            return true;
        }
     }

    private readonly dynamic viewBag;

    public BasePage()
    {
        viewBag = new DynamicViewState(this);
    }

    protected dynamic ViewBag
    {
        get { return viewBag; }
    }
}

Sample usage looks like this:

C#
public partial class SamplePage : BasePage
{
   protected void Page_Load(object sender, EventArgs e)
   {
       if (IsPostBack)
       {
           ViewBag.loadCount++;

           loadLabel.Text = string.Format("Load count: {0}", ViewState["loadCount"]);
       }
       else
       {
           ViewBag.loadCount = 0;
           loadLabel.Text = "Load count: 0";
       }
   }
}

As you can see we can mix ViewBag and ViewState together without any issues as ViewBag is simply a façade over ViewState.

If we also override TrySetIndex and TryGetIndex methods we can access ViewBag properties by using indexes exactly in the same way as ViewState. This is how final implementation look like:

C#
public class BasePage : Page
{
    private class DynamicViewState : DynamicObject
    {
        private readonly BasePage basePage;

        public DynamicViewState(BasePage basePage)
        {
            this.basePage = basePage;
        }

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            basePage.ViewState[binder.Name] = value;
            return true;
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = basePage.ViewState[binder.Name];

            return true;
        }

        public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
        {
            if (indexes.Length == 1)
            {
                basePage.ViewState[indexes[0].ToString()] = value;
                return true;
            }
            return base.TrySetIndex(binder, indexes, value);
        }

        public override bool TryGetIndex(GetIndexBinder binder, 
               object[] indexes, out object result)
        {
            if (indexes.Length == 1)
            {
                result = basePage.ViewState[indexes[0].ToString()];
                return true;
            }
            return base.TryGetIndex(binder, indexes, out result);
        }
    }

    private readonly dynamic viewBag;

    public BasePage()
    {
        viewBag = new DynamicViewState(this);
    }

    protected dynamic ViewBag
    {
        get { return viewBag; }
    }
}

Apart from dynamic ViewState, the above approach can be also used for providing similar implementations for Session, Cache, and similar objects.

Full source code with a demo application is available at Dynamic ViewState in ASP.NET WebForms.

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