Click here to Skip to main content
15,867,568 members
Articles / Web Development / ASP.NET

Dynamic ViewState in ASP.NET WebForms

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
18 Jan 2012CPOL2 min read 20.8K   3   2
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Georgia Georgia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionStateBag Pin
Richard Deeming24-Jan-12 6:24
mveRichard Deeming24-Jan-12 6:24 
AnswerRe: StateBag Pin
Giorgi Dalakishvili24-Jan-12 8:35
mentorGiorgi Dalakishvili24-Jan-12 8:35 
Thanks for your comment. Actually I have already made the exact change and the DynamicViewState also implements all the interfaces that StateBag implements so you can swap it completely. You can also rename the new property to ViewState and use the new approach. Source code is available at https://github.com/Giorgi/Dynamic-ViewState-in-ASP.Net-WebForms[^]
Giorgi Dalakishvili

#region signature

My Articles

My Blog

#endregion

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.