The ParseChildren PersistChildren and PersistenceMode.InnerProperty

After a while of non-web control development, ParseChildren and PersistChildren attributes are important attributes to remember when trying to get the desired results your looking for in the Visual Studio designer.

So, this post should clear up (and serve as a reminder for me) how and why these attributes are important.  Let's explore what these two attributes are used for.  Let's start with ParseChildren.

The [ParseChildrenAttribute]

The ParseChildren Attribute is probably, the most important attribute you should pay attention to when developing web controls.  It's actually used by the ASP.NET Parser and ControlBuilder object to figure out how to parse the ASP.NET code you write.  Visual Studio also uses this attribute to figure out what valid sub-controls and components are allowed within the contents of a server control.

Let's say, I want to create an AggregateFeeds control that displays an aggregate list of RSS feeds.

A Basic and Boring Control Syntax

image

You'll notice that the RssResource is the only available option that is allowed as a child from the AggregateFeeds control.  Here's the code behind the AggregateFeeds control:

  113     [

  114     ParseChildren(

  115         typeof(RssResource),

  116         DefaultProperty = "Feeds",

  117         ChildrenAsProperties = true

  118         )

  119     ]

  120     public class AggregateFeeds : Control

  121     {

  122         public AggregateFeeds()

  123         {

  124             this.Feeds = new RssFeedCollection();

  125         }

  126         public RssFeedCollection Feeds

  127         {

  128             get;

  129             private set;

  130         }

  131         protected override void Render(HtmlTextWriter writer)

  132         {

  133             this.Feeds

  134                 .ForEach( rssRes => writer.Write( rssRes.Url ) );

  135         }

  136     }

  137 

  138     public class RssFeedCollection : List<RssResource>

  139     {

  140 

  141     }

  142 

  143     public class RssResource

  144     {

  145         public string Url { get; set; }

  146     }

The ParseChildren attribute on AggregateFeeds tells the ASP.NET, that any children within the AggregateFeeds control should be typeof(RssResource)ChildrenAsProperties=true let's ASP.NET know that it should STOP parsing server controls with "runat=server", and switch to instantiating objects into the properties of the ArggregateFeeds control.  DefaultProperty says, that the results of the parsed objects should go into the default property Feeds.

Syntax Goodness With InnerProperty

The previous example was great, it's simple and get's the job done.  But let's say, the requirements have changed, our control is growing, and we need to allow more customization, and extensibility for the consumers of our AggregateFeeds control.

Let's clean up the markup and allow our developers to create markup like this:

image

To get this type of syntactical behavior, check out the code below:

  113     [

  114     ParseChildren(

  115         ChildrenAsProperties = true

  116         )

  117     ]

  118     public class AggregateFeeds : Control

  119     {

  120         public AggregateFeeds()

  121         {

  122             this.Feeds = new RssFeedCollection();

  123         }

  124 

  125         [PersistenceMode(PersistenceMode.InnerProperty)]

  126         public RssFeedCollection Feeds

  127         {

  128             get;

  129             private set;

  130         }

  131         [PersistenceMode(PersistenceMode.InnerProperty)]

  132         public AggregateSettings Settings

  133         {

  134             get;

  135             private set;

  136         }

  137         protected override void Render(HtmlTextWriter writer)

  138         {

  139             this.Feeds

  140                 .ForEach( rssRes => writer.Write( rssRes.Url ) );

  141         }

  142 

  143     }

  144 

  145     public class AggregateSettings

  146     {

  147         public int TimeOut { get; set; }

  148         public bool CacheResults { get; set; }

  149     }

  150 

  151     public class RssFeedCollection : List<RssResource>

  152     {

  153 

  154     }

  155 

  156     public class RssResource

  157     {

  158         public string Url { get; set; }

  159     }

Notice, we've removed DefaultProperty and typeof(RssResource) from ParseChildren attribute.  We're no longer working with a simple control that has simple children objects that need to be parsed, we're now working with a complex control with more than one property that we're setting in the markup, so we've removed the "default" stuff.  The syntactical magic happens with PersitanceMode attribute on the properties.  PersistanceMode.InnerProperty allows us to specify our cool <Feeds> and <Settings> tags.  How does Visual Studio know what members are available?  It does so by Reflection.

Get fancy, more than one child type

Also, I want to point out, suppose, we want to support multiple types of Feed objects.  We could use an enum in RssResource, or we could use inheritance to achieve the following:

image

All we would have to do is simply mark RssResource as an abstract class. Then, subclass for each type.

  156     public abstract class RssResource

  157     {

  158         public string Url { get; set; }

  159     }

  160     public class MediaRss : RssResource

  161     {

  162 

  163     }

  164     public class ITunesRss : RssResource

  165     {

  166 

  167     }

Again, I'm just showing that it's possible, but following my mantra of "less code, less maintenance," I'd use an enum to describe the type of rss feed on RssResource.

Where is [PersistChildren]?

Nowhere!  Is PersistChildren attribute needed?  No, it's not a required attribute to create your custom control.  The PersistChildrenAttribute only provides designer support for your control with Visual Studio and has no "processing" affect in ASP.NET, but remember ParseChildren does.

I'm a image  source-view only guy.  I really don't remember the last time I've used the Visual Studio "Design View", it's a waste, crashes all the time, so I've pretty much given up on it.  Besides, "Design View" is for n00bs anyway.  Just kidding!  If you plan on using the Design View, then you'll probably need your PersistChildren attribute...

In general, PersistChildren and ParseChildren are exclusive complementary attributes to describe the same semantic operation.  The rule of thumb goes:

If ParseChildren(true), then PersistChildren(false)

If ParseChildren(false), then PersistChildren(true).

Following the PersistChildren guideline above should keep your code out of trouble.  But again, I wouldn't use PersistChildren only until you actually need it.  Less code, less maintenance.

Here's a nice list of attributes you should consider when writing your custom controls:

http://wdevs.blogspot.com/2007/10/attributes-to-consider-applying-when.html

Hope that helps! Happy coding!

Brian Chavez

Comments

# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Great article!
Left by sulfur_scatch on 9/21/2008 12:44 PM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Nice article. You've explained these attributes better than the MSDN documentation ever has, and clearer than any other article I've found the last few years :)
Left by Perry Loh on 9/29/2008 8:57 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Superb article!!
Left by sandeep on 12/13/2008 9:57 PM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Just what I needed - I've was trying to figure out how to do this all day. Thanks!
Left by Jim on 1/15/2009 5:30 PM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Like it.... 5/5
Left by Srećko on 3/12/2009 3:51 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Thank you for very good example. I have a question: Does an example in a "Get fancy, more than one child type" work when I don't use an abstract base class?

I have ClassB : ClassA, no abstract,
and I uses it as a property:
[PersistenceMode(PersistenceMode.InnerProperty)]
public List<ClassA> ToolBarSettings{
... }

However I always get an error Unknown server tag 'CRM:ClassB' when I try to use it in this way:
<ToolBarSettings>
<CRM:ClassA CommandName="NEWTASK" />
<CRM:ClassA CommandName="EDIT" />
<CRM:ClassB CommandName="XYZ" />
</ToolBarSettings>

Thank you
Left by Jiří Nouza on 4/6/2009 10:29 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Found the answer: it works even it is not an abstract class.
I unfortunatelly forgot one class in another namespace which seems as a problem.
Left by Jiří Nouza on 4/7/2009 4:31 AM
# 
Gravatar Good References
Left by Amarbir's Blog on 7/27/2009 9:59 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Great article
Left by Guido Tapia on 8/11/2009 7:42 PM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Great article.

But I still have some problems here... I just can't get this to work in my case :S Bad luck I guess.
Left by Neikius on 10/30/2009 4:32 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar An amazing article...!!!
Left by Aleh on 2/23/2010 3:07 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Nice article
thanks...
Left by nishad on 3/20/2012 12:24 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar I keep coming back to this article, because it explains it better than most. But I still have two questions, hopefully you can answer these:

1. What determines the tag prefix for the inner properties? Is it always the same as the tag prefix for the control itself?

2. What type should the collection property minimally be? IS it ICollection? Or IList? I think it should support Add(), but I'm not sure if it can be ICollection<T> for instance.

Thanks!
Left by Mike on 8/7/2012 4:41 PM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Great article, the best of read in a long time. I've been trying to understand ParseChildren & PersistChildren for a while - you explain it simple and to the point. Well Done!
Left by Dov on 10/14/2012 12:23 AM
# re: The ParseChildren PersistChildren and PersistenceMode.InnerProperty
Gravatar Very nice article and very useful for beginners.
Left by Soundar on 2/5/2014 9:17 PM

Leave Your Comment

Title*
Name*
Email (never displayed)
 (will show your gravatar)
Url
Comment*

Please add 7 and 3 and type the answer here:

Preview Your Comment.