Click here to Skip to main content
Click here to Skip to main content

Dynamic ViewState in ASP.NET WebForms

, 18 Jan 2012
Rate this:
Please Sign up or sign in to vote.
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:

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:

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:

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:

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:

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)

About the Author

Giorgi Dalakishvili
Software Developer
Georgia Georgia
No Biography provided
Follow on   Google+

Comments and Discussions

 
QuestionStateBag PinmemberRichard Deeming24-Jan-12 6:24 
AnswerRe: StateBag PinmentorGiorgi Dalakishvili24-Jan-12 8:35 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 18 Jan 2012
Article Copyright 2012 by Giorgi Dalakishvili
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid