My head is absolutely pounding badly! I have done this before but not as "in depth" or complex as this and I have tried different ways to make this happen but all has failed.
So, this is the custom XML I want in the app.config:
<Profiles> <!--Collection-->
<Profile Name="Live">
<Components>
<Component Name="Portal" Type="Web" />
<Component Name="Comms" Type="Web" />
<Component Name="Scheduler" Type="WindowsService" ServiceName="LiveScheduler" />
</Components>
<Databases>
<Database Name="Main" Connection="Data Source=.\SQL2008" />
<Database Name="Staging" Connection="Data Source=SomeSite.co.uk" />
</Databases>
</Profile>
<Profile Name="Test">
<Components>
<Component Name="Portal" Type="Web" />
<Component Name="Comms" Type="Web" />
<Component Name="Scheduler" Type="WindowsService" ServiceName="TestScheduler" />
</Components>
<Databases>
<Database Name="Main" Connection="Data Source=.\SQL2008" />
<Database Name="Staging" Connection="Data Source=Internal" />
</Databases>
</Profile>
</Profiles>
So a collection of Profile with each profile having a collection of sub elements (Components is a collection, then Component is an element)
However I currently have all that EXCEPT for the multiple profiles. I kind of do see the problem but not sure how to "fix" it.
Code:
public class Profile : ConfigurationSection
{
[ConfigurationProperty("Name", IsRequired=true)]
public string Name
{
get
{
return base["Name"] as string;
}
set
{
base["Name"] = value;
}
}
[ConfigurationProperty("Components")]
public ComponentCollection Components
{
get { return ((ComponentCollection)(base["Components"])); }
}
[ConfigurationProperty("Databases")]
public DatabaseCollection Databases
{
get
{
return ((DatabaseCollection)(base["Databases"]));
}
}
}
[ConfigurationCollection(typeof(Component), AddItemName="Component")]
public class ComponentCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new Component();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Component)(element)).Name;
}
public Component this[int idx]
{
get
{
return base.BaseGet(idx) as Component;
}
set
{
if (base.BaseGet(idx) != null)
{
base.BaseRemoveAt(idx);
}
this.BaseAdd(idx, value);
}
}
public Component this[string key]
{
get
{
return base.BaseGet(key) as Component;
}
set
{
if (base.BaseGet(key) != null)
{
base.BaseRemove(key);
}
this.BaseAdd(this.Count, value);
}
}
}
public class Component : ConfigurationElement
{
[ConfigurationProperty("Type", IsRequired = true)]
public string Type
{
get
{
return this["Type"] as string;
}
set
{
this["Type"] = value;
}
}
[ConfigurationProperty("Name", IsRequired = true, IsKey = true)]
public string Name
{
get
{
return this["Name"] as string;
}
set
{
this["Name"] = value;
}
}
[ConfigurationProperty("ServiceName", IsRequired = false)]
public string ServiceName
{
get
{
return this["ServiceName"] as string;
}
set
{
this["ServiceName"] = value;
}
}
}
[ConfigurationCollection(typeof(Database), AddItemName = "Database")]
public class DatabaseCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new Database();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Database)(element)).Name;
}
public Database this[int idx]
{
get
{
return base.BaseGet(idx) as Database;
}
set
{
if (base.BaseGet(idx) != null)
{
base.BaseRemoveAt(idx);
}
this.BaseAdd(idx, value);
}
}
public Database this[string key]
{
get
{
return base.BaseGet(key) as Database;
}
set
{
if (base.BaseGet(key) != null)
{
base.BaseRemove(key);;
}
this.BaseAdd(this.Count, value);
}
}
}
public class Database : ConfigurationElement
{
[ConfigurationProperty("Name", IsKey = true, IsRequired = true)]
public string Name
{
get
{
return this["Name"] as string;
}
set
{
this["Name"] = value;
}
}
[ConfigurationProperty("Connection", IsKey = false, IsRequired = true)]
public string Connection
{
get
{
return this["Connection"] as string;
}
set
{
this["Connection"] = value;
}
}
}
You need to move your configuration section one level higher.
public class Profiles : ConfigurationSection
{
[ConfigurationProperty("Profile")]
public ProfileCollection Profile
{
get
{
return this["profile"] as ProfileCollection;
}
}
}
Here's a section that I created. You should be able to get yours working by following this:
public class ImportConfiguration : ConfigurationSection
{
[ConfigurationProperty("importMap")]
public ImportMapElementCollection ImportMap
{
get
{
return this["importMap"] as ImportMapElementCollection;
}
}
}
public class ImportColumnMapElement : ConfigurationElement
{
[ConfigurationProperty("localName", IsRequired = true, IsKey = true)]
public string LocalName
{
get
{
return this["localName"] as string;
}
set
{
this["localName"] = value;
}
}
[ConfigurationProperty("sourceName", IsRequired = true)]
public string SourceName
{
get
{
return this["sourceName"] as string;
}
set
{
this["sourceName"] = value;
}
}
}
public class ImportMapElementCollection : ConfigurationElementCollection
{
public ImportColumnMapElement this[object key]
{
get
{
return base.BaseGet(key) as ImportColumnMapElement;
}
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName
{
get
{
return "columnMap";
}
}
protected override bool IsElementName(string elementName)
{
bool isName = false;
if (!String.IsNullOrEmpty(elementName))
isName = elementName.Equals("columnMap");
return isName;
}
protected override ConfigurationElement CreateNewElement()
{
return new ImportColumnMapElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ImportColumnMapElement)element).LocalName;
}
}
You're implementing correctly except you need one extra level. Change Profile from a ConfigurationSection to a ConfigurationElement, then make a ConfigurationSection Profiles that contains a collection of Profile items.
This is an excellent case for automated testing, debugging configuration sections without is a royal pain.
Related
So, I'm trying to make a custom configuration section for my app.config that will process the following pattern:
<domainSolutionSection>
<domainSolutionGroups>
<Group groupname="Legacy">
<add name="Old App #1"/>
<add name="Old App #2" />
</Group>
<Group groupname="Modern">
<add name="New App #1" />
<add name="New App #2" />
<add name="New App #3" />
</Group>
</domainSolutionGroups>
</domainSolutionSection>
I've spent all day trying to get this to work.
Right now, I'm getting an error:
System.Configuration.ConfigurationErrorsException: Unrecognized element 'add'.
Here are the classes in my DomainSolutionSection library:
public class DomainSolutionSection : ConfigurationSection
{
[ConfigurationProperty("domainSolutionGroups")]
public DomainSolutionGroupCollection DomainSolutionGroups
{
get
{
return (DomainSolutionGroupCollection) this["domainSolutionGroups"];
}
set
{
this["domainSolutionGroups"] = value;
}
}
}
[ConfigurationCollection(typeof(GroupConfigElement))]
public class DomainSolutionGroupCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new GroupConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((GroupConfigElement)element).GroupName;
}
protected override string ElementName
{
get { return "Group"; }
}
protected override bool IsElementName(string elementName)
{
return !String.IsNullOrEmpty(elementName) && elementName == "Group";
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
public GroupConfigElement this[int index]
{
get
{
return base.BaseGet(index) as GroupConfigElement;
}
}
public new GroupConfigElement this[string key]
{
get
{
return base.BaseGet(key) as GroupConfigElement;
}
}
}
public class GroupConfigElement : ConfigurationElement
{
[ConfigurationProperty("groupname", IsRequired = true, IsKey = true)]
public string GroupName
{
get { return (string)this["groupname"]; }
set { this["groupname"] = value; }
}
public PhraseCollection Phrases
{
get { return (PhraseCollection) base["Groups"]; }
}
}
[ConfigurationCollection(typeof(PhraseConfigElement), AddItemName = "add", CollectionType = ConfigurationElementCollectionType.BasicMap)]
public class PhraseCollection: ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new PhraseConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((PhraseConfigElement)element).Name;
}
}
public class PhraseConfigElement: ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
}
Not finding any examples out there where "add" properties are used at this level of nesting, so obviously, I haven't "wired-up" the "Group" properly. Can anybody offer any guidance?
Thanks!
Apologies that this is not a direct answer to your question. I don't have the time to break down what you have done, but here is a similar example of something that I have done in the past, and which works. Perhaps there's something in here to help.
myconfig.config:
<?xml version="1.0"?>
<myconfig>
<moduleIPAccessRules>
<allowRules>
<add module="ModuleA" subnetIP="172.16.0.0" subnetMask="255.255.0.0" name="ModuleA intranet users" />
<add module="ModuleA" subnetIP="127.0.0.0" subnetMask="255.255.0.0" name="ModuleA local box" />
<add module="ModuleB" subnetIP="172.16.0.0" subnetMask="255.255.0.0" name="ModuleB intranet users" />
<add module="ModuleB" subnetIP="127.0.0.0" subnetMask="255.255.0.0" name="ModuleB local box" />
<add module="ModuleB" subnetIP="123.45.67.89" subnetMask="255.255.255.255" name="some remote machine" />
</allowRules>
</moduleIPAccessRules>
</myconfig>
Backing class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
namespace Myproject.Configuration
{
public class IPAccessSection : ConfigurationSection
{
public static IPAccessSection GetConfig()
{
return ConfigurationManager.GetSection("myconfig/moduleIPAccessRules") as IPAccessSection;
}
[ConfigurationProperty("allowRules")]
public AllowRuleCollection AllowRules
{
get { return this["allowRules"] as AllowRuleCollection; }
}
}
public class AllowRuleCollection : ConfigurationElementCollection
{
public AllowRule this[int index]
{
get
{
return base.BaseGet(index) as AllowRule;
}
set
{
if (base.BaseGet(index) != null)
base.BaseRemoveAt(index);
this.BaseAdd(index, value);
}
}
protected override ConfigurationElement CreateNewElement()
{
return new AllowRule();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((AllowRule)element).Name;
}
}
public class AllowRule : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get { return this["name"] as string; }
}
[ConfigurationProperty("module", IsRequired = true)]
public string Module
{
get { return this["module"] as string; }
}
[ConfigurationProperty("subnetIP", IsRequired = true)]
public string SubnetIP
{
get { return this["subnetIP"] as string; }
}
[ConfigurationProperty("subnetMask", IsRequired = true)]
public string SubnetMask
{
get { return this["subnetMask"] as string; }
}
}
}
Actually, I just figured out the answer about 10 minutes ago. And it's basically that I hadn't really "hooked up" the PhraseCollection to the GroupConfigElement properly... nor had I fully fleshed-out the PhraseCollection.:
public class GroupConfigElement : ConfigurationElement
{
[ConfigurationProperty("groupname", IsRequired = true, IsKey = true)]
public string GroupName
{
get { return (string)this["groupname"]; }
set { this["groupname"] = value; }
}
[ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
public PhraseCollection Phrases
{
get { return (PhraseCollection) base[""]; }
}
}
[ConfigurationCollection(typeof(PhraseConfigElement))]
public class PhraseCollection: ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new PhraseConfigElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((PhraseConfigElement)element).Name;
}
public PhraseConfigElement this[int index]
{
get
{
return base.BaseGet(index) as PhraseConfigElement;
}
}
public new PhraseConfigElement this[string key]
{
get
{
return base.BaseGet(key) as PhraseConfigElement;
}
}
}
public class PhraseConfigElement: ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
}
}
The key fixes were to the "Phrases" definition... and then I had to add those two public methods to the "PhraseCollection" definition.
Thanks!
Hi can any one suggest the way to write the custom configuration class for writing the configuration as follows in my app.config file.
<configuration>
<configSections>
<section name="oneP2CReportConfiguration" type="MyDll.Config.CustomConfig.OnePage2ColReportConfigInfo, MyDll.Config"/>
</configSections>
<oneP2CReportConfiguration>
<countryGroup>
<country name="India">
<country name="Japan">
</countryGroup>
<countryGroup>
<country name="China">
<country name="Nepal">
</countryGroup>
</oneP2CReportConfiguration>
</configuration>
Finally I figured it out how to write the custom configuration file.
C# Code
namespace Custom.Configs
{
public class OnePage2CountryReportConfig : ConfigurationSection
{
[ConfigurationProperty("", IsDefaultCollection = true)]
public CountryGroupCollection Members
{
get
{
CountryGroupCollection countryGroupCollection = (CountryGroupCollection)base[""];
return countryGroupCollection;
}
}
}
public class CountryGroupCollection : ConfigurationElementCollection
{
public CountryGroupCollection()
{
CountryGroupElement details = (CountryGroupElement)CreateNewElement();
if (details.Name != "")
{
Add(details);
}
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override ConfigurationElement CreateNewElement()
{
return new CountryGroupElement();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((CountryGroupElement)element).Name;
}
public CountryGroupElement this[int index]
{
get
{
return (CountryGroupElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
{
BaseRemoveAt(index);
}
BaseAdd(index, value);
}
}
new public CountryGroupElement this[string name]
{
get
{
return (CountryGroupElement)BaseGet(name);
}
}
public int IndexOf(CountryGroupElement details)
{
return BaseIndexOf(details);
}
public void Add(CountryGroupElement details)
{
BaseAdd(details);
}
protected override void BaseAdd(ConfigurationElement element)
{
BaseAdd(element, false);
}
public void Remove(CountryGroupElement details)
{
if (BaseIndexOf(details) >= 0)
BaseRemove(details.Name);
}
public void RemoveAt(int index)
{
BaseRemoveAt(index);
}
public void Remove(string name)
{
BaseRemove(name);
}
public void Clear()
{
BaseClear();
}
protected override string ElementName
{
get { return "countryGroup"; }
}
}
public class CountryCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new Country();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((Country)element).CountryCode;
}
protected override string ElementName
{
get
{
return "country";
}
}
protected override bool IsElementName(string elementName)
{
return !String.IsNullOrEmpty(elementName) && elementName == "country";
}
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
public Country this[int index]
{
get
{
return base.BaseGet(index) as Country;
}
}
public new Country this[string key]
{
get
{
return base.BaseGet(key) as Country;
}
}
}
public class CountryGroupElement : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
[StringValidator(InvalidCharacters = " ~!##$%^&*()[]{}/;’\"|\\")]
public string Name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("", IsDefaultCollection = true, IsKey = false, IsRequired = true)]
public CountryCollection Countries
{
get { return base[""] as CountryCollection; }
set
{
base[""] = value;
}
}
}
public class Country : ConfigurationElement
{
[ConfigurationProperty("code", IsRequired = true, IsKey = true)]
[StringValidator(InvalidCharacters = " ~!##$%^&*()[]{}/;’\"|\\")]
public string CountryCode { get { return (string)this["code"]; } }
}
}
app.config
<configSections>
<section name="onePage2CountryReportConfigSection" type="Custom.Configs.OnePage2CountryReportConfig, Custom.Config"/>
</configSections>
<onePage2CountryReportConfigSection>
<countryGroup name="group1">
<country code="JAP"/>
<country code="NEP"/>
</countryGroup>
<countryGroup name="group2">
<country code="IND"/>
<country code="BAN"/>
<country code="SRI"/>
<country code="PHI"/>
</countryGroup>
</onePage2CountryReportConfigSection>
I am trying to create a custom config section for holding some API credentials following the tutorial at: http://devlicio.us/blogs/derik_whittaker/archive/2006/11/13/app-config-and-custom-configuration-sections.aspx . I have added the following to my Web.config file:
<!-- Under configSections -->
<section name="providers" type="EmailApiAccess.Services.ProviderSection, EmailApiAccess.Services"/>
<!-- Root Level -->
<providers>
<add name="ProviderName" username="" password ="" host="" />
</providers>
and have created the following classes:
public class ProviderSection: ConfigurationSection
{
[ConfigurationProperty("providers")]
public ProviderCollection Providers
{
get { return ((ProviderCollection)(base["providers"])); }
}
}
[ConfigurationCollection(typeof(ProviderElement))]
public class ProviderCollection : ConfigurationElementCollection
{
public ProviderElement this[int index]
{
get { return (ProviderElement) BaseGet(index); }
set
{
if (BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((ProviderElement)(element)).name;
}
protected override ConfigurationElement CreateNewElement()
{
return new ProviderElement();
}
}
public class ProviderElement: ConfigurationElement
{
public ProviderElement() { }
[ConfigurationProperty("name", DefaultValue="", IsKey=true, IsRequired=true)]
public string name
{
get { return (string)this["name"]; }
set { this["name"] = value; }
}
[ConfigurationProperty("username", DefaultValue = "", IsRequired = true)]
public string username
{
get { return (string)this["username"]; }
set { this["username"] = value; }
}
[ConfigurationProperty("password", DefaultValue = "", IsRequired = true)]
public string password
{
get { return (string)this["password"]; }
set { this["password"] = value; }
}
[ConfigurationProperty("host", DefaultValue = "", IsRequired = false)]
public string host
{
get { return (string)this["host"]; }
set { this["host"] = value; }
}
}
However, when I try and implement the code using this:
var section = ConfigurationManager.GetSection("providers");
ProviderElement element = section.Providers["ProviderName"];
var creds = new NetworkCredential(element.username, element.password);
I get an error saying that 'Object' does not contain a definition for 'Providers'....
Any help would be appreciated.
ConfigurationManager.GetSection returns a value of type object, not your custom config section. Try the following:
var section = ConfigurationManager.GetSection("providers") as ProviderSection;
Based on my app.config I would like to be able to get the elements of columns as shown in the example below in lines 3-5. How should I write the code in order to achieve this. If I'll need to change my app.config - I'll do it.
1. var bounceProviders = ConfigurationManager.GetSection("BounceProviders") as BounceProvidersSection;
2. var providerColumns = bounceProviders.Providers[0].Columns;
3. var emailColumn = providerColumns.Email;
4. var dateColumn = providerColumns.Date;
5. var messageColumn = providerColumns.Message;
app.config
<BounceProviders>
<Providers>
<Provider Name="p1">
<Columns>
<Email Name="My Email" />
<Date Name="My Date" />
<Message Name="My Message" />
</Columns>
</Provider>
<Provider Name="p2">
<Columns />
</Provider>
</Providers>
</BounceProviders>
ConfigurationSection
public class BounceProvidersSection : ConfigurationSection
{
[ConfigurationCollection(typeof(ConfigCollection<BounceProviderConfig>), AddItemName = "Provider")]
[ConfigurationProperty("Providers", IsRequired = true)]
public ConfigCollection<BounceProviderConfig> Providers
{
get { return (ConfigCollection<BounceProviderConfig>)this["Providers"]; }
set { this["Providers"] = value; }
}
}
public class BounceProviderConfig : ConfigurationElement
{
[ConfigurationProperty("Name", IsRequired = true)]
public string Name
{
get { return (string)this["Name"]; }
set { this["Name"] = value; }
}
}
ConfigCollection
public class ConfigCollection<T> : ConfigurationElementCollection
where T : ConfigurationElement, new()
{
protected override ConfigurationElement CreateNewElement()
{
return new T();
}
protected override object GetElementKey( ConfigurationElement element )
{
return element.GetHashCode();
}
public T this[int index]
{
get
{
return ( T )BaseGet( index );
}
set
{
if ( BaseGet( index ) != null )
{
BaseRemoveAt( index );
}
BaseAdd( index, value );
}
}
new public T this[string Name]
{
get
{
return ( T )BaseGet( Name );
}
}
}
sdf
I figured it out
public class BounceProvidersSection : ConfigurationSection
{
[ConfigurationCollection(typeof(ConfigCollection<BounceProviderConfig>), AddItemName = "Provider")]
[ConfigurationProperty("Providers", IsRequired = true)]
public ConfigCollection<BounceProviderConfig> Providers
{
get { return (ConfigCollection<BounceProviderConfig>)this["Providers"]; }
set { this["Providers"] = value; }
}
}
public class BounceProviderConfig : ConfigurationElement
{
[ConfigurationProperty("Id", IsRequired = true)]
public int Id
{
get { return (int)this["Id"]; }
set { this["Id"] = value; }
}
[ConfigurationProperty("Columns", IsRequired = false)]
public BounceProviderColumns Columns
{
get { return (BounceProviderColumns)this["Columns"]; }
set { this["Columns"] = value; }
}
public static BounceProviderConfig GetByProviderId(int providerId)
{
var section = ConfigUtils.GetConfigurationSection<BounceProvidersSection>("BounceProviders");
foreach (BounceProviderConfig provider in section.Providers)
{
if (provider.Id == providerId)
return provider;
}
return null;
}
}
public class BounceProviderColumns : ConfigurationElement
{
[ConfigurationProperty("Email", IsRequired = true)]
public ColumnConfig Email
{
get { return (ColumnConfig)this["Email"]; }
set { this["Email"] = value; }
}
[ConfigurationProperty("Date", IsRequired = true)]
public DateColumnConfig Date
{
get { return (DateColumnConfig)this["Date"]; }
set { this["Date"] = value; }
}
[ConfigurationProperty("Message", IsRequired = true)]
public ColumnConfig Message
{
get { return (ColumnConfig)this["Message"]; }
set { this["Message"] = value; }
}
}
public class ColumnConfig : ConfigurationElement
{
[ConfigurationProperty("Name", IsRequired = true)]
public string Name
{
get { return (string)this["Name"]; }
set { this["Name"] = value; }
}
}
I'm having trouble getting a custom config section to work. It's some code I got from the web in an effort to try to understand this area a little better and enable me to get to where I want to ultimatly be, my own custom config section.
The error I get when I run the code in a console app is
'
Unrecognized attribute 'extension'. Note that attribute names are case-sensitive.'
The code in the main app to get things going is
var conf = ConfigurationManager.GetSection("uploadDirector");
and this is where the exception appears.
This is the config section I am hoping/trying to achieve
<AuthorisedClients>
<AuthorisedClient name="Client">
<Queue id="1" />
<Queue id="7" />
</AuthorisedClient>
<AuthorisedClient name="Client2">
<Queue id="3" />
<Queue id="4" />
</AuthorisedClient>
</AuthorisedClients>
Here's the code I have got from the web
.config file
<uploadDirector>
<filegroup name="documents" defaultDirectory="/documents/">
<clear/>
<add extension="pdf" mime="application/pdf" maxsize="100"/>
<add extension="doc" mime="application/word" maxsize="500"/>
</filegroup>
<filegroup name="images">
<clear/>
<add extension="gif" mime="image/gif" maxsize="100"/>
</filegroup>
</uploadDirector>
UploadDirectorConfigSection.cs
public class UploadDirectorConfigSection : ConfigurationSection {
private string _rootPath;
public UploadDirectorConfigSection() {
}
[ConfigurationProperty("rootpath", DefaultValue="/", IsRequired=false, IsKey=false)]
[StringValidator(InvalidCharacters=#"~!.##$%^&*()[]{};'\|\\")]
public string RootPath {
get { return _rootPath; }
set { _rootPath = value; }
}
[ConfigurationProperty("", IsRequired = true, IsKey = false, IsDefaultCollection = true)]
public FileGroupCollection FileGroups {
get { return (FileGroupCollection) base[""]; }
set { base[""] = value; }
}
}
FileGroupCollection.cs
public class FileGroupCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() {
return new FileGroupElement();
}
protected override object GetElementKey(ConfigurationElement element) {
return ((FileGroupElement) element).Name;
}
public override ConfigurationElementCollectionType CollectionType {
get {
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override string ElementName {
get {
return "filegroup";
}
}
protected override bool IsElementName(string elementName) {
if (string.IsNullOrWhiteSpace(elementName) || elementName != "filegroup")
return false;
return true;
}
public FileGroupElement this[int index] {
get { return (FileGroupElement) BaseGet(index); }
set {
if(BaseGet(index) != null)
BaseRemoveAt(index);
BaseAdd(index, value);
}
}
}
FileGroupElement.cs
public class FileGroupElement : ConfigurationElement {
[ConfigurationProperty("name", IsKey=true, IsRequired = true)]
[StringValidator(InvalidCharacters = #" ~.!##$%^&*()[]{}/;'""|\")]
public string Name {
get { return (string) base["name"]; }
set { base["name"] = value; }
}
[ConfigurationProperty("defaultDirectory", DefaultValue = ".")]
public string DefaultDirectory {
get { return (string) base["Path"]; }
set { base["Path"] = value; }
}
[ConfigurationProperty("", IsDefaultCollection = true, IsRequired = true)]
public FileInfoCollection Files {
get { return (FileInfoCollection) base[""]; }
}
}
FileInfoCollection.cs
public class FileInfoCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() {
return new FileInfoCollection();
}
protected override object GetElementKey(ConfigurationElement element) {
return ((FileInfoElement) element).Extension;
}
}
FileInfoElement.cs
public class FileInfoElement : ConfigurationElement {
public FileInfoElement() {
Extension = "txt";
Mime = "text/plain";
MaxSize = 0;
}
[ConfigurationProperty("extension", IsKey = true, IsRequired = true)]
public string Extension {
get { return (string)base["extension"]; }
set { base["extension"] = value; }
}
[ConfigurationProperty("mime", DefaultValue = "text/plain")]
public string Mime {
get { return (string) base["mime"]; }
set { base["mime"] = value; }
}
[ConfigurationProperty("maxsize", DefaultValue = 0)]
public int MaxSize {
get { return (int) base["maxsize"]; }
set { base["maxsize"] = value; }
}
}
In your definition of FileInfoCollection in the method CreateNewElement you create FileInfoCollection which is wrong. Overridden CreateNewElement should return new collection element, not the new collection:
public class FileInfoCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return new FileInfoElement();
}
protected override object GetElementKey (ConfigurationElement element)
{
return ((FileInfoElement)element).Extension;
}
}
Regarding your desired configuration, probably the simplest implementation will look like:
public class AuthorisedClientsSection : ConfigurationSection {
[ConfigurationProperty("", IsDefaultCollection = true)]
public AuthorisedClientElementCollection Elements {
get { return (AuthorisedClientElementCollection)base[""];}
}
}
public class AuthorisedClientElementCollection : ConfigurationElementCollection {
const string ELEMENT_NAME = "AuthorisedClient";
public override ConfigurationElementCollectionType CollectionType {
get { return ConfigurationElementCollectionType.BasicMap; }
}
protected override string ElementName {
get { return ELEMENT_NAME; }
}
protected override ConfigurationElement CreateNewElement() {
return new AuthorisedClientElement();
}
protected override object GetElementKey(ConfigurationElement element) {
return ((AuthorisedClientElement)element).Name;
}
}
public class AuthorisedClientElement : ConfigurationElement {
const string NAME = "name";
[ConfigurationProperty(NAME, IsRequired = true)]
public string Name {
get { return (string)base[NAME]; }
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public QueueElementCollection Elements {
get { return (QueueElementCollection)base[""]; }
}
}
public class QueueElementCollection : ConfigurationElementCollection {
const string ELEMENT_NAME = "Queue";
public override ConfigurationElementCollectionType CollectionType {
get { return ConfigurationElementCollectionType.BasicMap; }
}
protected override string ElementName {
get { return ELEMENT_NAME; }
}
protected override ConfigurationElement CreateNewElement() {
return new QueueElement();
}
protected override object GetElementKey(ConfigurationElement element) {
return ((QueueElement)element).Id;
}
}
public class QueueElement : ConfigurationElement {
const string ID = "id";
[ConfigurationProperty(ID, IsRequired = true)]
public int Id {
get { return (int)base[ID]; }
}
}
And the test:
var authorisedClientsSection = ConfigurationManager.GetSection("AuthorisedClients")
as AuthorisedClientsSection;
foreach (AuthorisedClientElement client in authorisedClientsSection.Elements) {
Console.WriteLine("Client: {0}", client.Name);
foreach (QueueElement queue in client.Elements) {
Console.WriteLine("\tQueue: {0}", queue.Id);
}
}