Collection property Hell on an ASP.NET Server Control
I’ve been fighting an odd problem today with a custom control I’m building. The control is another extender control that has a number of child items that track other items on the form. The markup looks something like this:
<ww:LocalizationExtender id="Localizer" runat="server">
<LocalizationItems>
<ww:LocalizationItem ControlId="lblMessage"
Property="Text" runat="server"
EnableLocalization="true"
LocalizationType="GlobalString">
</ww:LocalizationItem>
<ww:LocalizationItem ControlId="btnSubmit"
Property="Text"
EnableLocalization="true"
LocalizationType="GlobalString">
</ww:LocalizationItem>
</LocalizationItems>
</ww:LocalizationExtender>
The logic in the control works fine at runtime. But when the control renders I get this error display:

Haeh? The problem is that LocalizationItems is a collection and it doesn’t have a LocalizationExtender property and well nothing of the sort gets set on LocalizationItems or the child items. Something isn’t wired right but I can’t figure out what the heck it is. I compared with other controls that have this same setup and it all looks right, but it looks that the designer is very unhappy.
It seems like an attribute mismatch, but I can’t see it in the code.
[ToolboxData("<{0}:LocalizationExtender runat=server />")]
//[ProvideProperty("LocalizationItem", typeof(Control))]
[NonVisualControl, Designer(typeof(LocalizationExtenderDesigner))]
[ParseChildren(true, "LocalizationItems")]
[PersistChildren(false)]
//[DefaultProperty("LocalizationItems")]
//[DefaultEvent("ValidateControl")]
public class LocalizationExtender : Control //, IExtenderProvider
{
private new bool DesignMode = HttpContext.Current == null;
/// <summary>
/// A collection of the individual Localization Items for the control
/// that track each of the controls on the page that are localized.
/// </summary>
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[Browsable(true)]
public LocalizationItemCollection LocalizationItems
{
get { return _Items; }
set { _Items = value; }
}
private LocalizationItemCollection _Items = new LocalizationItemCollection();
The collection just inherits from CollectionBase. I get the same error if I replace the manual collection with a List<LocalizationItem> - in fact I created the manual collection because of this damn error since this is the only difference I see between this control and another.
If take the child items out of the page, the control renders fine. If leave just the collection in place it too renders fine. But as soon as a child item is added into the collection in the designer it fails. The designer will let me add items visually and persist them fine. However, once I switch into markup and then back to the designer the control is hosed again.
I’ve tried to debug into this and see if I can capture the code failing somewhere, but even attached to the debugger into a second instance in VS I can’t find the spot that’s a problem. The main control OnInit() fires fine, but beyond that I get nothing. No collection or item constructors (presumably because they’re deserializing somehow) – nothing to hook code to and the debugger is not throwing exception dialogs either…
I’m stumped and I’m out of ideas on how to track this down… Anybody have any ideas? I need a little push <g>…
Other Posts you might also like
- Adding minimal OWIN Identity Authentication to an Existing ASP.NET MVC Application
- Resolving Paths To Server Relative Paths in .NET Code
- Map Physical Paths with an HttpContext.MapPath() Extension Method in ASP.NET
- Back to Basics: Rewriting a URL in ASP.NET Core
- Getting the Client IP Address in ASP.NET Core
The Voices of Reason
# re: Collection property Hell on an ASP.NET Server Control
I spent almost an entire day on this a while ago, it makes not logical sense to me why the setting property would make a difference... but hey, mine is not to question why :p
# re: Collection property Hell on an ASP.NET Server Control
# re: Collection property Hell on an ASP.NET Server Control
A better error message might help though <g>...
# re: Collection property Hell on an ASP.NET Server Control
# re: Collection property Hell on an ASP.NET Server Control
# re: Collection property Hell on an ASP.NET Server Control
http://msdn2.microsoft.com/en-us/library/9txe1d4x.aspx
http://msdn2.microsoft.com/en-us/library/9zky1t4k.aspx
# re: Collection property Hell on an ASP.NET Server Control
It took me a while to figure out why the designer didn't let me edit that property, but simply switching to List (or List<>) did the trick.
# re: Collection property Hell on an ASP.NET Server Control
If you don't get one by default you can create CollectionEditor and assign it. It's really simple to implement - all you need to do is provide the target type of the children and ASP.NET will do the rest.
But using List<> is usually the easiest unless you need mroe control (as I do for this control).
# re: Collection property Hell on an ASP.NET Server Control
One more thing which is not told in the docs is that the inner type of the property collection must reside in the same namespace of the control or you'll need to register that other namespace with the <%@ Register %> directive because it doesn't get recognized and considered as an HtmlGenericControl.
# re: Collection property Hell on an ASP.NET Server Control
# re: Collection property Hell on an ASP.NET Server Control
[Editor(typeof(CollectionEditor), typeof(UITypeEditor))]
is working as well in design mode.
# re: Collection property Hell on an ASP.NET Server Control
# re: Collection property Hell on an ASP.NET Server Control
"set { _Items = value; }"
Without this line it works fine!
# re: Collection property Hell on an ASP.NET Server Control
componentChangeService.OnComponentChanging(myControl, myControlPropertyDescriptor);
then
componentChangeService.OnComponentChanged(myControl, myControlPropertyDescriptor, oldValue, newValue);
So please do anyone have a solution for this. Note that i have another property of type ITemplate also it did the same problem but when i changed that to PropertyDescripto.SetValue it worked fine in the panel, yeah sure because it has a setter but in the case of the collection i cant because it does not have a setter. In fact even if i add a setter a public one it didn't work for the collection.
I hope to hear from you guys. thanks.
# re: Collection property Hell on an ASP.NET Server Control
Thanks to Simone comment (regarding HtmlGenericControl problem) I could solve a problem that was a headache for the last years.
Cheers
Jaime
# re: Collection property Hell on an ASP.NET Server Control
I need to create a custom server control with collection properties for the following markup... This server control parses content retrieved from a CMS for tokens delimited by "[[" and "]]" chars. The markup looks like this...
<ww:ContentBlock ID="CB1" runat="server" ContentBlockName=""> <DataTokens> <ww:DataToken ID="CB1DT1" runat="server"> <%= ListingObject.ListingTitle %> </ww:DataToken> <ww:DataToken ID="CB1DT2" runat="server"> <%= ListingObject.ListingDescription %> </ww:DataToken> </DataTokens> </ww:ContentBlock>
My question is, how do I make the parser bind the "ListingObject" page property from the code-behind to the custom control's collection property???
Thanks,
Marzban
# re: Collection property Hell on an ASP.NET Server Control
It turns out the Property Setter of the Collection property was the problem:
set { _Items = value; }
Removing the Setter makes everything work just peachy. I'm not sure why the absence or existance of a Setter should make a difference to ASP.NET. In fact it seems like a setter would be required in order for ASP.NET...
At the very least it'd be nice if there was a sensible error message that kind of hinted at the problem...
<sigh> there go another couple of hours of a wild goosechase. Hopefully this will help somebody else out.