Nested ConfigurationElementCollections

M

Mark Olbert

I'd like to create a ConfigurationSection to handle something that looks like this:

<SiteSettings>
<site name="develop" smtp="mail.arcabama.com" host="localhost">
<mappings>
<membership name="a" column="cola" />
<membership name="b" column="colb" />
</mappings>
</site>
<site name="production" smtp="smtp.alentus.com" host="www.arcabama.com">
<mappings>
<membership name="a" column="cola" />
<membership name="b" column="colb" />
</mappings>
</site>
</SiteSettings>

I thought I could do this with the following classes (sorry about the length):

public class SiteSection : ConfigurationSection
{
[ ConfigurationProperty("", IsDefaultCollection = true) ]
public SiteCollection Sites
{
get { return (SiteCollection) base[""]; }
}
}

public class SiteCollection : ConfigurationElementCollection
{
public new SiteElement this[string name]
{
get
{
if( IndexOf(name) < 0 ) return null;

return (SiteElement) BaseGet(name);
}
}

public SiteElement this[int index]
{
get { return (SiteElement) BaseGet(index); }
}

public int IndexOf( string name )
{
name = name.ToLower();

for( int idx = 0; idx < base.Count; idx++ )
{
if( this[idx].Name.ToLower() == name )
return idx;
}

return -1;
}

public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}

protected override ConfigurationElement CreateNewElement()
{
return new SimpleSiteSetting();
}

protected override object GetElementKey( ConfigurationElement element )
{
return ( (SiteElement) element ).Name;
}

protected override string ElementName
{
get { return "site"; }
}
}

public class SiteElement : ConfigurationElement
{
[ ConfigurationProperty("name", DefaultValue = "develop", IsRequired = true, IsKey = true) ]
public string Name
{
get { return (string) this["name"]; }
set { this["name"] = value; }
}

[ ConfigurationProperty("smtp", DefaultValue = "mail.arcabama.com", IsRequired = true, IsKey = false) ]
public string SmtpServer
{
get { return (string) this["smtp"]; }
set { this["smtp"] = value; }
}

[ ConfigurationProperty("host", DefaultValue = "localhost", IsRequired = true, IsKey = false) ]
public string Host
{
get { return (string) this["host"]; }
set { this["host"] = value; }
}

[ ConfigurationProperty("mappings", IsDefaultCollection = false) ]
public MembershipCollection Mappings
{
get { return (MembershipCollection) base["mappings"]; }
}
}

public class MembershipCollection : ConfigurationElementCollection
{
public new MembershipElement this[string name]
{
get
{
if( IndexOf(name) < 0 ) return null;

return (MembershipElement) BaseGet(name);
}
}

public MembershipElement this[int index]
{
get { return (MembershipElement) BaseGet(index); }
}

public int IndexOf( string name )
{
name = name.ToLower();

for( int idx = 0; idx < base.Count; idx++ )
{
if( this[idx].Name.ToLower() == name )
return idx;
}
return -1;
}

public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}

protected override ConfigurationElement CreateNewElement()
{
return new MembershipElement();
}

protected override object GetElementKey( ConfigurationElement element )
{
return ( (MembershipElement) element ).Name;
}

protected override string ElementName
{
get { return "membership"; }
}
}

public class MembershipElement : ConfigurationElement
{
[ ConfigurationProperty("name", DefaultValue = "", IsRequired = true, IsKey = true) ]
public string Name
{
get { return (string) this["name"]; }
set { this["name"] = value; }
}

[ ConfigurationProperty("column", DefaultValue = "", IsRequired = true, IsKey = false) ]
public string Column
{
get { return (string) this["column"]; }
set { this["column"] = value; }
}
}

But while I can watch the methods in MembershipCollection get called -- and see that the web.config entries corresponding to the
MembershipElements are being parsed -- the Mappings collection in SiteElement always ends up being empty.

How do I go about nesting one ConfigurationElementCollection within another?

- Mark
 
L

Luke Zhang [MSFT]

Hello Mark,

I got different results with same code, the Mappings collection in
SiteElement return correct result. Here is the code I used (I tested in a
winform application):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>



<configSections>

<section
name="SiteSettings"
type="WindowsApplication8.SiteSection,WindowsApplication8"
allowLocation="true"
allowDefinition="Everywhere" />


</configSections>


<SiteSettings>
<site name="develop" smtp="mail.arcabama.com" host="localhost">
<mappings>
<membership name="a" column="cola" />
<membership name="b" column="colb" />
</mappings>
</site>
<site name="production" smtp="smtp.alentus.com" host="www.arcabama.com">
<mappings>
<membership name="a" column="cola" />
<membership name="b" column="colb" />
</mappings>
</site>



</SiteSettings>


</configuration>



SiteSection configSection =
(SiteSection)System.Configuration.ConfigurationManager.GetSection("SiteSetti
ngs");

propertyGrid1.SelectedObject = configSection;
 
M

Mark Olbert

Interesting. But I'm using this as part of a website. Why would the same code work in a WinForm, but not in a website?

- Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top