2.0: Nested configuration data

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,
I'm trying to specify multiple child collection under a ConfigurationSection.

I have
<asystems name="pippo">
<asystem newName="Production"/>
<asystem newName="dev"/>
<anotherItem newName="yuk"/>
<anotherItem newName="yuk111"/>
</asystems>

It seems that only one colleciton colud be specified,
[ConfigurationProperty("", IsDefaultCollection = true)]
public SystemsCollection Systems
{
get
{
return (SystemsCollection)base[""];
}
}

To retrive the simpler config

<asystems name="pippo">
<asystem newName="Production"/>
<asystem newName="dev"/>
</asystems>

with a given name like

[ConfigurationProperty("asystem", IsDefaultCollection = false)]
public SystemsCollection Systems
{
get
{
return (SystemsCollection)base["asystem"];
}
}

did not work.
Any idea?
 
Hi Carlo,

Welcome to the MSDN newsgroup.

As for declaring custom configureation section and sub nested config
elements, in .NET 2.0, we could use the custom classes derived from
ConfigurationSection, ConfigurationElement and
ConfigurationElementCollection classes. And the
"ConfigurationElementCollection" is the one we used for collection based
configure element. And we can define multile sub configElement of this type
in a single custom configuration section. Here is the msdn reference on how
to use the ConfigurationElementCollection type to define colleciton based
configuration element:

#ConfigurationElementCollection Class
http://msdn2.microsoft.com/en-us/library/system.configuration.configuratione
lementcollection(VS.80).aspx

Hope this helps.

Regards,

Steven Cheng
Microsoft Online Community Support


==================================================

When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.

==================================================


This posting is provided "AS IS" with no warranties, and confers no rights.



Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 
Hi,
what I'm trying to do is to handle this xml
----------------------------------------------------
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="systems" type="TestConfiguration.SystemsSection,
TestSerializzazioneCOnfigurazione" />
</configSections>
<systems name="pippo">
<asystem newAName="name A 1"/>
<asystem newAName="name A 2"/>
<bsystem newBName="name B 1"/>
<bsystem newBName="name B 2"/>
</systems>
<configuration>
--------------------------------------------

in the form load I do
-----------------------------------------------
private void Form1_Load(object sender, EventArgs e)
{

TestConfiguration.SystemsSection sysSection =
ConfigurationManager.GetSection("systems")
as TestConfiguration.SystemsSection;
TestConfiguration.AsystemCollection aCollection = sysSection.Asystem;
foreach (TestConfiguration.AsystemElement aElement in aCollection)
{
Console.WriteLine(aElement.ToString());

}
TestConfiguration.BsystemCollection bCollection = sysSection.Bsystem;
foreach (TestConfiguration.BsystemElement bElement in bCollection)
{
Console.WriteLine(bElement.ToString());

}
}

---------------------------------------------
the ConfigSection classes are defined as follow
----------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Configuration; // remember to add reference in project
using System.Reflection;
namespace TestConfiguration
{
public sealed class SystemsSection : ConfigurationSection
{
public SystemsSection()
{
}
[ConfigurationProperty("asystem", IsDefaultCollection = false)]
public AsystemCollection Asystem
{
get
{
AsystemCollection a = (AsystemCollection)base["asystem"];
return (AsystemCollection)base["asystem"];
}
}
[ConfigurationProperty("bsystem", IsDefaultCollection = false)]
public BsystemCollection Bsystem
{
get
{
BsystemCollection b = (BsystemCollection)base["bsystem"];
return (BsystemCollection)base["bsystem"];
}
}
}
public sealed class AsystemCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new AsystemElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((AsystemElement)element).newAName;
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "asystem";
}
}
}
public sealed class AsystemElement : ConfigurationElement
{
[ConfigurationProperty("newAName", IsKey = false, IsRequired = false)]
public string newAName
{
get
{
return (string)base["newAName"];
}
set
{
base["newAName"] = value;
}
}

public override string ToString()
{
string output = "AsystemElement :\n";
output += string.Format("AName = {0}\n", newAName);
return output;
}
}

public sealed class BsystemCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new BsystemElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((BsystemElement)element).newBName;
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "bsystem";
}
}
}
public sealed class BsystemElement : ConfigurationElement
{
[ConfigurationProperty("newBName", IsKey = false, IsRequired = false)]
public string newBName
{
get
{
return (string)base["newBName"];
}
set
{
base["newBName"] = value;
}
}

public override string ToString()
{
string output = "BsystemElement :\n";
output += string.Format("BName = {0}\n", newBName);
return output;
}
}

}
------------------------------------------------

When I run this program I get

Unrecognized attribute 'newAName'.

What I'm doing wrong?
 
Sorry,
to get to the error I posted delete the attribute name="pippo" (wrong cut 'n
paste)
 
Hi Carlo,

Thank you for the response and the further description.

So in the web.config you provided, you're mixing the asystem and bsystem
element in a single colleciton element "systems", then, what is type of the
"systems" element? Is it "asystemcollection" or "bsystemcollection"? We can
not make a single collection contains child element of different types. So
for your scenario, you need to use two collections to hold the different
type elements. e.g:




<MyUrls >
<urls>

<url name="Microsoft1" url="http://www.microsoft1.com" port="0" />
<url name="Microsoft2" url="http://www.microsoft2.com" port="0" />
<url name="Microsoft3" url="http://www.microsoft3.com" port="0" />


</urls>


<imgUrls>
<imgUrl name="Image1" url="http://www.microsoft.com/image1.jpg" />
<imgUrl name="Image2" url="http://www.microsoft.com/image2.jpg" />
<imgUrl name="Image3" url="http://www.microsoft.com/image3.jpg" />
</imgUrls>
</MyUrls>


and in our section class, we define two associated collection properties,
like:

==============================
public class UrlsSection : ConfigurationSection
{
..........................................


[ConfigurationProperty("urls")]
public UrlsCollection Urls
{
get
{ return (UrlsCollection)this["urls"]; }
set
{ this["urls"] = value; }
}

[ConfigurationProperty("imgUrls")]
public ImageUrlsCollection ImageUrls
{
get
{ return (ImageUrlsCollection)this["imgUrls"]; }
set
{ this["imgUrls"] = value; }
}
}
=======================================


Regards,

Steven Cheng
Microsoft Online Community Support


==================================================

When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.

==================================================


This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Steven,
I was thinking that you map the different node name to different types with
an xpath query, something like
aSystemsNodes = confDom.SelectNodes("systems/asystem")
bSystemsNodes = confDom.SelectNodes("systems/bsystem")

I tried with your xml, getting similar error.
It seems that the collection root element name must be equal to the
collection elements node name,
<MyUrls>
<url>
<url name="Microsoft1" url="http://www.microsoft1.com" port="0" />
<url name="Microsoft2" url="http://www.microsoft2.com" port="0" />
<url name="Microsoft3" url="http://www.microsoft3.com" port="0" />
</url>
.....

I'm doing something wrong?
Following the conf and code for your sample xml with my workaround....
----------------------------------------
<configuration>
<configSections>
<section name="MyUrls" type="TestConfiguration.MsConf.UrlsSection,
TestSerializzazioneCOnfigurazione" />
</configSections>
<MyUrls>
<url>
<url name="Microsoft1" url="http://www.microsoft1.com" port="0" />
<url name="Microsoft2" url="http://www.microsoft2.com" port="0" />
<url name="Microsoft3" url="http://www.microsoft3.com" port="0" />
</url>
<imgUrls>
<imgUrls name="Image1" url="http://www.microsoft.com/image1.jpg" />
<imgUrls name="Image2" url="http://www.microsoft.com/image2.jpg" />
<imgUrls name="Image3" url="http://www.microsoft.com/image3.jpg" />
</imgUrls>
</MyUrls>
</configuration>
------------------------------------
with the following configSection class
-----------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Specialized;
using System.Configuration; // remember to add reference in project
using System.Reflection;
namespace TestConfiguration.MsConf
{
public sealed class UrlsSection : ConfigurationSection
{
public UrlsSection()
{
}
[ConfigurationProperty("url")]
public UrlsCollection Urls
{
get
{
UrlsCollection a = (UrlsCollection)base["url"];
return (UrlsCollection)base["url"];
}
set
{ this["url"] = value; }
}
[ConfigurationProperty("imgUrls")]
public ImageUrlsCollection ImageUrls
{
get
{ return (ImageUrlsCollection)this["imgUrls"]; }
set
{ this["imgUrls"] = value; }
}
}
public sealed class UrlsCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new UrlsElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((UrlsElement)element).Name;
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "url";
}
}
}
public sealed class UrlsElement : ConfigurationElement
{
[ConfigurationProperty("name")]
public string Name
{
get
{
return (string)base["name"];
}
set
{
base["name"] = value;
}
}

[ConfigurationProperty("url")]
public string Url
{
get
{
return (string)base["url"];
}
set
{
base["url"] = value;
}
}

[ConfigurationProperty("port")]
public string Port
{
get
{
return (string)base["port"];
}
set
{
base["port"] = value;
}
}

public override string ToString()
{
string output = "urls :\n";
output += string.Format("urls = {0}\n", Name + Url +Port);
return output;
}
}

public sealed class ImageUrlsCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new ImageUrlsElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ImageUrlsElement)element).Name;
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "imgUrls";
}
}
}
public sealed class ImageUrlsElement : ConfigurationElement
{
[ConfigurationProperty("name", IsKey = false, IsRequired = false)]
public string Name
{
get
{
return (string)base["name"];
}
set
{
base["name"] = value;
}
}

[ConfigurationProperty("url", IsKey = false, IsRequired = false)]
public string Url
{
get
{
return (string)base["url"];
}
set
{
base["url"] = value;
}
}

public override string ToString()
{
string output = "ImageUrl :\n";
output += string.Format("ImageUrl = {0}\n", Name + Url);
return output;
}
}

}
----------------------------------------------------------
private void Form1_Load(object sender, EventArgs e)
{

TestConfiguration.MsConf.UrlsSection sysSection =
ConfigurationManager.GetSection("MyUrls")
as TestConfiguration.MsConf.UrlsSection;
TestConfiguration.MsConf.UrlsCollection aCollection =
sysSection.Urls;
foreach (TestConfiguration.MsConf.UrlsElement aElement in
aCollection)
{
Console.WriteLine(aElement.ToString());

}
TestConfiguration.MsConf.ImageUrlsCollection bCollection =
sysSection.ImageUrls;
foreach (TestConfiguration.MsConf.ImageUrlsElement bElement in
bCollection)
{
Console.WriteLine(bElement.ToString());

}
 
Thanks for your response Carlo,

Seems something else cause this not work. Anyway, below is the complete
class code and ASP.NET webconfig setting for that custom section:

==========custom config classes============
namespace ConfigLib
{

public class UrlsSection : ConfigurationSection
{
public UrlsSection()
{
}

public UrlsSection(String attribVal)
{
MyAttrib1 = attribVal;
}

[ConfigurationProperty("myAttrib1", DefaultValue = "Clowns",
IsRequired = true)]
[StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;'\"|\\",
MinLength = 1, MaxLength = 60)]
public String MyAttrib1
{
get
{ return (String)this["myAttrib1"]; }
set
{ this["myAttrib1"] = value; }
}

[ConfigurationProperty("baseUrl")]
public UrlConfigElement BaseUrl
{
get
{ return (UrlConfigElement)this["baseUrl"]; }
set
{ this["baseUrl"] = value; }
}


[ConfigurationProperty("urls")]
public UrlsCollection Urls
{
get
{ return (UrlsCollection)this["urls"]; }
set
{ this["urls"] = value; }
}

[ConfigurationProperty("imgUrls")]
public ImageUrlsCollection ImageUrls
{
get
{ return (ImageUrlsCollection)this["imgUrls"]; }
set
{ this["imgUrls"] = value; }
}
}




public class UrlsCollection : ConfigurationElementCollection
{
public UrlsCollection()
{ }

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

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


protected override
ConfigurationElement CreateNewElement(
string elementName)
{
return new UrlConfigElement(elementName);
}


protected override Object
GetElementKey(ConfigurationElement element)
{
return ((UrlConfigElement)element).Name;
}

protected override string ElementName
{
get
{
return "url";
}
}
//public new string AddElementName
//{
// get
// { return base.AddElementName; }

// set
// { base.AddElementName = value; }

//}

//public new string ClearElementName
//{
// get
// { return base.ClearElementName; }

// set
// { base.AddElementName = value; }

//}

//public new string RemoveElementName
//{
// get
// { return base.RemoveElementName; }


//}

public new int Count
{

get { return base.Count; }

}


public UrlConfigElement this[int index]
{
get
{
return (UrlConfigElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}

new public UrlConfigElement this[string Name]
{
get
{
return (UrlConfigElement)BaseGet(Name);
}
}

public int IndexOf(UrlConfigElement url)
{
return BaseIndexOf(url);
}

public void Add(UrlConfigElement url)
{
BaseAdd(url);

// Add custom code here.
}

protected override void
BaseAdd(ConfigurationElement element)
{
BaseAdd(element, false);
// Add custom code here.
}

public void Remove(UrlConfigElement url)
{
if (BaseIndexOf(url) >= 0)
BaseRemove(url.Name);
}

public void RemoveAt(int index)
{
BaseRemoveAt(index);
}

public void Remove(string name)
{
BaseRemove(name);
}

public void Clear()
{
BaseClear();
// Add custom code here.
}
}







public class ImageUrlsCollection : ConfigurationElementCollection
{
public ImageUrlsCollection()
{ }

public override
ConfigurationElementCollectionType CollectionType
{
get
{
return

ConfigurationElementCollectionType.BasicMap;
}
}

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


protected override
ConfigurationElement CreateNewElement(
string elementName)
{
return new ImageUrlConfigElement(elementName);
}


protected override Object
GetElementKey(ConfigurationElement element)
{
return ((ImageUrlConfigElement)element).Name;
}

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



public ImageUrlConfigElement this[int index]
{
get
{
return (ImageUrlConfigElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}

new public ImageUrlConfigElement this[string Name]
{
get
{
return (ImageUrlConfigElement)BaseGet(Name);
}
}

public int IndexOf(ImageUrlConfigElement url)
{
return BaseIndexOf(url);
}

public void Add(ImageUrlConfigElement url)
{
BaseAdd(url);

// Add custom code here.
}

protected override void
BaseAdd(ConfigurationElement element)
{
BaseAdd(element, false);
// Add custom code here.
}

public void Remove(ImageUrlConfigElement url)
{
if (BaseIndexOf(url) >= 0)
BaseRemove(url.Name);
}

public void RemoveAt(int index)
{
BaseRemoveAt(index);
}

public void Remove(string name)
{
BaseRemove(name);
}

public void Clear()
{
BaseClear();
// Add custom code here.
}
}



public class UrlConfigElement : ConfigurationElement
{
public UrlConfigElement()
{
}

public UrlConfigElement(string name)
{
Name = name;

}

public UrlConfigElement(string name, string url)
{
Name = name;
Url = url;
}

[ConfigurationProperty("name", IsRequired = true)]
public String Name
{
get
{ return (String)this["name"]; }
set
{ this["name"] = value; }
}

[ConfigurationProperty("url", IsRequired = true)]
public String Url
{
get
{ return (String)this["url"]; }
set
{ this["url"] = value; }
}

[ConfigurationProperty("port")]
public int Port
{
get
{ return (int)this["port"]; }
set
{ this["port"] = value; }
}
}


public class ImageUrlConfigElement : ConfigurationElement
{
public ImageUrlConfigElement()
{
}

public ImageUrlConfigElement(string name)
{
Name = name;

}

public ImageUrlConfigElement(string name, string url)
{
Name = name;
Url = url;
}

[ConfigurationProperty("name", IsRequired = true)]
public String Name
{
get
{ return (String)this["name"]; }
set
{ this["name"] = value; }
}

[ConfigurationProperty("url", IsRequired = true)]
public String Url
{
get
{ return (String)this["url"]; }
set
{ this["url"] = value; }
}


}
}
=====================================


========webconfig file=========
<configuration>
<configSections>
<section name="MyUrls" type="ConfigLib.UrlsSection, ConfigLib"
allowDefinition="Everywhere" allowExeDefinition="MachineToApplication"
restartOnExternalChanges="true"/>
<!-- Other <section> and <sectionGroup> elements. -->
</configSections>
<MyUrls myAttrib1="Clowns">
<urls>
<url name="Microsoft1" url="http://www.microsoft1.com" port="0"/>
<url name="Microsoft2" url="http://www.microsoft2.com" port="0"/>
<url name="Microsoft3" url="http://www.microsoft3.com" port="0"/>
</urls>
<imgUrls>
<imgUrl name="Image1" url="http://www.microsoft.com/image1.jpg"/>
<imgUrl name="Image2" url="http://www.microsoft.com/image2.jpg"/>
<imgUrl name="Image3" url="http://www.microsoft.com/image3.jpg"/>
</imgUrls>
</MyUrls>
===========================

Hope this helps.

Regards,

Steven Cheng
Microsoft Online Community Support


==================================================

When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.

==================================================


This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Steven,
got it!

The name of the root xml node for the collection is specified in the
UrlsSection class (in this case "Urls") the name of the child nome is
specified in the ElementName property of UrlsCollection class ("Url")

public sealed class UrlsSection : ConfigurationSection
{
........
[ConfigurationProperty("urls")]
public UrlsCollection Urls
{
get { return (UrlsCollection)base["urls"]; }
set { this["urls"] = value; }
}
}

public sealed class UrlsCollection : ConfigurationElementCollection
{
.......
protected override string ElementName
{ get { return "url";}}
}

Thank you for helping me understand.
Ciao
 
That's Cool Carlo!

Glad to be of assistance :).

Have a good day!

Regards,

Steven Cheng
Microsoft Online Community Support


==================================================

When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.

==================================================


This posting is provided "AS IS" with no warranties, and confers no rights.
 
Hi Carlo,

How i can read the following config file.

<Site Run="True">
<Line Name="Line1" Run="True">
<Station Name="Station1" Run="True"></Station>
<Station Name="Station2" Run="True"></Station>
</Line>
<Line Name="Line2" Run="True">
<Station Name="Station3" Run="True"></Station>
<Station Name="Station4" Run="True"></Station>
</Line>
</Site>

Please reply ASAP. Its urgent for me.

Regs
Satya
 
My problem haven't solved yet.
I just want to write config file

....
....
<objectTypes>
<state name="State" type=".....">
<controller name = "controller1" type=".....">
<controller name = "Controller2" type=".....">
......
......
</objectTypes>

thats all.. Different types of configurationelements under same
configurationelementcollection and added without "add", thanks

and please do not give me any "url" example. they are not same
things...
<urls>
<url .... >
<url .....>
</urls>
thanks
 
Back
Top