Search code examples
winformsconfigurationapp-configcustom-configuration

Problem with Custom Configuration Settings


I added a custom section to my app.config file for a Windows Forms Application. I created the class to extend the configuration file:

CustomFields myCustomFields = (CustomFields)System.Configuration.ConfigurationManager.GetSection("CustomFields");

I specify the section name:

<section name="CustomFields" type="Application.Core.CustomFields, ATMCardRequest.Core" allowLocation="true" allowDefinition="Everywhere" />

Now here is where I think the issue is. The above has worked fine before but I need a lot of properties for this section and instead of doing this:

<CustomFields setting1='hello' setting2='world'/>

I am doing this:

<CustomFields>
<property name="setting1">hello</property>
<property name="setting2">world</property>
...
</CustomFields>

Code:

 /// <summary>
    /// Settings file which holds the name of the XML Fields 
    /// </summary>
    public class setting1: ConfigurationSection
    {

        /// <summary>
        /// Name of the setting1 Field 
        /// </summary>
        [ConfigurationProperty("setting1", IsRequired = true)]
        public String setting1
        {
            get
            {
                return (String)this["setting1"];
            }
            set
            {
                this["setting1"] = value;
            }
        }

        /// <summary>
        /// Name of the setting2 Field
        /// </summary>
        [ConfigurationProperty("setting2",IsRequired = true)]
        public String setting2
        {
            get
            {
                return (String)this["setting2"];
            }
            set
            {
                this["setting2"] = value;
            }
        }
}
}

Which isn't working. Apparently it doesn't understand the 'property' syntax.

Any ideas what I am doing wrong? Thanks.


Solution

  • If would define the properties that you need this way:

    <CustomFields>
        <property name="setting1">hello</property>
        <property name="setting2">world</property>
        ...
    </CustomFields>
    

    than each "property" becomes child node for CustomFields and your properties are now attributes/values for those child nodes, not attributes of the CustomFields node as in the first example.

    If you have lot of properties and you want to set them more elegantly here are two options that might consider:

    1) Use the following structure for the custom section (slightly changed):

    <CustomFields>
        <setting1 value="hello"/>
        <setting2 value="world"/>
        ...   
    </CustomFields>
    

    and the following code to define the properties used to retrieve the values:

    public class CustomFields: ConfigurationSection
    {            
        [ConfigurationProperty("setting1")]
        public PropertyElement Setting1
        {
            get
            {
                return (PropertyElement)this["setting1"];
            }
            set
                { this["setting1"] = value; }
        }
    
        [ConfigurationProperty("setting2")]
        public PropertyElement Setting2
        {
            get
            {
                return (PropertyElement)this["setting2"];
            }
            set
                { this["setting2"] = value; }
        }
    }  
    public class PropertyElement : ConfigurationElement
    {
        [ConfigurationProperty("value", IsRequired = false)]
        public String Value
        {
            get
            {
                return (String)this["value"];
            }
            set
            {
                this["value"] = value;
            }
        }
    }
    

    Then, to retrieve the values:

    string setting1value = myCustomFields.Setting1.Value;
    string setting2value = myCustomFields.Setting2.Value;
    

    For details please see How to: Create Custom Configuration Sections Using ConfigurationSection on MSDN.

    2) Take a programmatic approach instead of relying on attributes and reflection. ConfigurationSection class or IConfigurationSectionHandler could be used in this case. As a result you will have access from code to the xml node containing the custom section data and will be able to load any kind of XML structure.