Saving server control properties to ViewState with custom attributes

One thing I don’t like about creating ASP.NET server controls is you end up with a lot of properties that look like this:

  1. public class PieControl1 : Control{
  2.     …
  3.     public int Pies
  4.     {
  5.         get
  6.         {
  7.             if (ViewState["Pies"] != null)
  8.                 return (int)ViewState["Pies"];
  9.             return 0;
  10.         }
  11.         set { ViewState["Pies"] = value;}
  12. }

It’s dull, dull, dull code to write! We are programmers. Our job is to dream of beautiful abstractions and clever solutions to difficult problems. It is our machine underlings who should do the boring work like this!

Fortunately, there is an alternative. C# has a really nifty feature called Attributes that you can use to add meta data to your class. If you’ve made server controls before you’ve probably used them for things like web resources, toolbox information and serialization.

So we just need to create a new attribute:

  1. [AttributeUsage(AttributeTargets.Property)]
  2. public class PersistToViewState : Attribute
  3. {
  4. }

And then just add it to any property in the server control that should get persisted in ViewState. If you’re using the property shorthand in C# 3.5 you can end up with properties that are only one line long:

  1. public class PieControl : BaseControl
  2. {
  3.     …
  4.     [PersistToViewState]
  5.     public string PieType { get; set; }
  6.  
  7.     [PersistToViewState]
  8.     public int Pies { get; set; }
  9. }

Now it’s possible to use a little reflection to figure out which properties need to be saved. Load the viewstate information into the control in LoadViewState and then save it back again in SaveViewState. In my example, I put it in a BaseControl so all my controls can use the same logic:

  1. public class BaseControl : Control
  2. {
  3.     protected override void LoadViewState(object savedState)
  4.     {
  5.         base.LoadViewState(savedState);
  6.         PropertyInfo[] properties = GetType().GetProperties();
  7.         foreach (PropertyInfo property in properties)
  8.         {
  9.             object[] attributes = property.GetCustomAttributes(typeof(PersistToViewState), true);
  10.             if (attributes.Length < 0)
  11.             {
  12.                 if (ViewState[property.Name] != null)
  13.                     property.SetValue(this, ViewState[property.Name], null);
  14.             }
  15.         }
  16.     }
  17.     protected override object SaveViewState()
  18.     {
  19.         PropertyInfo[] properties = GetType().GetProperties();
  20.         foreach (PropertyInfo property in properties)
  21.         {
  22.             object[] attributes = property.GetCustomAttributes(typeof(PersistToViewState), true);
  23.             if (attributes.Length < 0)
  24.                 ViewState[property.Name] = property.GetValue(this, null);
  25.         }
  26.         return base.SaveViewState();
  27.     }
  28. }

Here’s a complete example.

For more information there’s a follow up post that shows how to use this technique to optimize the amount of viewstate generated.

Posted on 13 Aug 08 by Helen Emerson (last updated on 13 Oct 09).
Filed under Server controls