The Problem
I have a custom configuration section with a nested configuration collection. I have moved the main custom configuration section to its own file as so:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="my.section" type="My.App.CustomSection, My.App" />
</configSections>
<my.section configSource="app\custom.config" />
</configuration
and for app\custom.config
:
<?xml version="1.0" encoding="utf-8"?>
<my.section>
<children>
<child configSource="children\child1.config" />
</children>
</my.section>
And my children file at app\children\child1.config
:
<?xml version="1.0" encoding="utf-8"?>
<child name="myChild">
...
</child>
In app\custom.config
the <children>
element is implemented as a ConfigurationElementCollection
and works if the child elements are in-lined, but I'm seeing an exception with the message "Unrecognized attribute 'configSource'. Note that attribute names are case-sensitive." on the <child configSource="children\child1.config" />
line in the custom.config file.
The Question
Is it possible to use the configSource
attribute for elements in a child of a config collection? If so, what might I be doing wrong here?
For now, I'll use in-lined children - however it would be very useful to be able to use custom config sources in our situation so any answer will be much appreciated.
Notes
NOTE 1: In case my paths were wrong I've also tried making the path relative to the root web.config and even moving all of the configs to the root folder - this had no effect on the error.
NOTE 2: I have read this question and ensured that I meet the conditions specified in the accepted (and only) answer - my config files are being output in the bin folder and they all have the appropriate <?xml version="1.0" encoding="utf-8" ?>
declaration.
UPDATE:
As requested in the comments by Jonesy, the ConfigurationSection code:
public class CustomSection : ConfigurationSection
{
private static readonly ConfigurationPropertyCollection properties;
private static readonly ConfigurationProperty children;
static CustomSection()
{
children = new ConfigurationProperty(
"children",
typeof( ChildSectionCollection ),
null,
ConfigurationPropertyOptions.IsRequired
);
properties = new ConfigurationPropertyCollection
{
children
};
}
protected override ConfigurationPropertyCollection Properties
{
get { return properties; }
}
[ConfigurationProperty( "children", IsRequired = true )]
public ChildSectionCollection ChildrenSection
{
get { return ( ChildSectionCollection ) base[ children ]; }
}
}
and:
public class ChildSection : ConfigurationSection
{
private static readonly ConfigurationPropertyCollection properties;
private static readonly ConfigurationProperty name;
static ChildSection()
{
name = new ConfigurationProperty(
"name",
typeof( string ),
string.Empty,
ConfigurationPropertyOptions.IsRequired
);
properties = new ConfigurationPropertyCollection
{
name
};
}
[ConfigurationProperty( "name", IsRequired = true )]
public string Name
{
get { return ( string ) base[ name ]; }
}
protected override ConfigurationPropertyCollection Properties
{
get { return properties; }
}
}
and:
[ConfigurationCollection( typeof( ChildSection ), CollectionType = ConfigurationElementCollectionType.BasicMap, AddItemName = "child" )]
public class ChildSectionCollection : ConfigurationElementCollection
{
private static readonly ConfigurationPropertyCollection properties;
static ChildSectionCollection()
{
properties = new ConfigurationPropertyCollection();
}
protected override ConfigurationPropertyCollection Properties
{
get { return properties; }
}
protected override ConfigurationElement CreateNewElement()
{
return new ChildSection();
}
protected override object GetElementKey( ConfigurationElement element )
{
return ( ( ChildSection ) element ).Name;
}
public override ConfigurationElementCollectionType CollectionType
{
get { return ConfigurationElementCollectionType.BasicMap; }
}
protected override string ElementName
{
get { return "child"; }
}
}
and, lastly:
var customSection = ( CustomSection ) ConfigurationManager.GetSection( "my.section" );
NOTE 3: The design of my code is based upon Jon Rista's CodeProject article Unraveling the Mysteries of .NET 2.0 Configuration.