How to Create Custom Config Section in App.Config

How to create custom config section in app.config?

Import namespace :

using System.Configuration;

Create ConfigurationElement Company :

public class Company : ConfigurationElement
{

[ConfigurationProperty("name", IsRequired = true)]
public string Name
{
get
{
return this["name"] as string;
}
}
[ConfigurationProperty("code", IsRequired = true)]
public string Code
{
get
{
return this["code"] as string;
}
}
}

ConfigurationElementCollection:

public class Companies
: ConfigurationElementCollection
{
public Company this[int index]
{
get
{
return base.BaseGet(index) as Company ;
}
set
{
if (base.BaseGet(index) != null)
{
base.BaseRemoveAt(index);
}
this.BaseAdd(index, value);
}
}

public new Company this[string responseString]
{
get { return (Company) BaseGet(responseString); }
set
{
if(BaseGet(responseString) != null)
{
BaseRemoveAt(BaseIndexOf(BaseGet(responseString)));
}
BaseAdd(value);
}
}

protected override System.Configuration.ConfigurationElement CreateNewElement()
{
return new Company();
}

protected override object GetElementKey(System.Configuration.ConfigurationElement element)
{
return ((Company)element).Name;
}
}

and ConfigurationSection:

public class RegisterCompaniesConfig
: ConfigurationSection
{

public static RegisterCompaniesConfig GetConfig()
{
return (RegisterCompaniesConfig)System.Configuration.ConfigurationManager.GetSection("RegisterCompanies") ?? new RegisterCompaniesConfig();
}

[System.Configuration.ConfigurationProperty("Companies")]
[ConfigurationCollection(typeof(Companies), AddItemName = "Company")]
public Companies Companies
{
get
{
object o = this["Companies"];
return o as Companies;
}
}

}

and you must also register your new configuration section in web.config (app.config):

<configuration>       
<configSections>
<section name="Companies" type="blablaNameSpace.RegisterCompaniesConfig, blablaAssemblyName" ..>

then you load your config with

var config = RegisterCompaniesConfig.GetConfig();
foreach(var item in config.Companies)
{
do something ..
}

Custom app.config section with a simple list of add elements

Full example with code based on OP config file:

<configuration>
<configSections>
<section name="registerCompanies"
type="My.MyConfigSection, My.Assembly" />
</configSections>
<registerCompanies>
<add name="Tata Motors" code="Tata"/>
<add name="Honda Motors" code="Honda"/>
</registerCompanies>
</configuration>

Here is the sample code to implement a custom config section with collapsed collection

using System.Configuration;
namespace My {
public class MyConfigSection : ConfigurationSection {
[ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)]
public MyConfigInstanceCollection Instances {
get { return (MyConfigInstanceCollection)this[""]; }
set { this[""] = value; }
}
}
public class MyConfigInstanceCollection : ConfigurationElementCollection {
protected override ConfigurationElement CreateNewElement() {
return new MyConfigInstanceElement();
}

protected override object GetElementKey(ConfigurationElement element) {
//set to whatever Element Property you want to use for a key
return ((MyConfigInstanceElement)element).Name;
}
}

public class MyConfigInstanceElement : ConfigurationElement {
//Make sure to set IsKey=true for property exposed as the GetElementKey above
[ConfigurationProperty("name", IsKey = true, IsRequired = true)]
public string Name {
get { return (string) base["name"]; }
set { base["name"] = value; }
}

[ConfigurationProperty("code", IsRequired = true)]
public string Code {
get { return (string) base["code"]; }
set { base["code"] = value; }
} } }

Here is an example of how to access the configuration information from code.

var config = ConfigurationManager.GetSection("registerCompanies") 
as MyConfigSection;

Console.WriteLine(config["Tata Motors"].Code);
foreach (var e in config.Instances) {
Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code);
}

Custom Config section in App.config C#

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="customAppSettingsGroup">
<section name="customAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</sectionGroup>
</configSections>
<customAppSettingsGroup>
<customAppSettings>
<add key="KeyOne" value="ValueOne"/>
<add key="KeyTwo" value="ValueTwo"/>
</customAppSettings>
</customAppSettingsGroup>
</configuration>

Usage:

NameValueCollection settings =  
ConfigurationManager.GetSection("customAppSettingsGroup/customAppSettings")
as System.Collections.Specialized.NameValueCollection;

if (settings != null)
{
foreach (string key in settings.AllKeys)
{
Response.Write(key + ": " + settings[key] + "<br />");
}
}

How do I add custom ConfigurationSection to Assembly?

If I understand correctly, you have problem with resolving what actually your Assembly is, since you are only creating .cs files that determine types that this file hold.

Assembly (in maybe not so accurate shorcut) is just the project you have in your solution. It will get compiled into its seperate assembly - the .dll you mentioned - later on.
When you add class to any .cs file in given project, on compile it will be included in project's assembly.

By default, if you won't provide assembly for configSection where its corresponding type should be found, App.config defaults to System.Configuration assembly - that's where you get your error from, since you've declared your section in your own assembly (== project).

Right click in Visual Studio on your project that holds App.config file and choose Properties to check its Assembly name:

Sample Image

Then add this name to your App.config section declaration. In my example its ConsoleApp1, so I will add it to configuration accordingly:

<configSections>
<section name="testSection" type="mssql_gui.TestConfigSection, ConsoleApp1"/>
</configSections>

Modify custom app.config config section and save it

System.Configuration.NameValueSectionHandler is hard to work with. You can replace it with System.Configuration.AppSettingsSection without touching anything else:

<configuration>
<configSections>
<section name="SpeedSection" type="System.Configuration.AppSettingsSection" />
</configSections>
<SpeedSection>
<add key="PrinterSpeed" value="150" />
<add key="CameraSpeed" value="150" />
</SpeedSection>
</configuration>

And then change your method as follows:

static void AddUpdateAppSettings(string key, string value)
{
try
{
var configFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var settings = ((AppSettingsSection) configFile.GetSection("SpeedSection")).Settings;
if (settings[key] == null)
{
settings.Add(key, value);
}
else
{
settings[key].Value = value;
}
configFile.Save(ConfigurationSaveMode.Modified);
ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
catch (ConfigurationErrorsException)
{
Console.WriteLine("Error writing app settings");
}
}

Custom configuration section in app.config - XML attributes Vs elements

As far as i know, you can't place values in xml sections in app.config file while using ConfigurationManager

But you have a quite similar option to work with config structures like that:

<DataSourcesConfig>
<DataSources>
<DataSource>
<name value="test1"/>
<connectionType value="Ethernet_TCP_Client"/>
<protocolType value="Serial"/>
<ipAddress value="127.0.0.1"/>
<port value="12345"/>
</DataSource>
<DataSource>
<name value="test2"/>
<connectionType value="Ethernet_TCP_Client"/>
<protocolType value="Serial"/>
<ipAddress value="127.0.0.1"/>
<port value="12346"/>
</DataSource>
</DataSources>
</DataSourcesConfig>

First of all, you need to define an ValueElement:

public class ValueElement<T> : ConfigurationElement
{
[ConfigurationProperty("value", IsRequired = true)]
public T Value => (T) this["value"];
}

Next, change your DataSource element like that:

public class DataSource : ConfigurationSection // It is section now
{
[ConfigurationProperty("name", IsRequired = true)]
public ValueElement<string> Name => this["name"] as ValueElement<string>;

[ConfigurationProperty("connectionType", IsRequired = true)]
public ValueElement<string> ConnectionType => this["connectionType"] as ValueElement<string>;

[ConfigurationProperty("protocolType", IsRequired = true)]
public ValueElement<string> ProtocolType => this["protocolType"] as ValueElement<string>;

[ConfigurationProperty("ipAddress", IsRequired = true)]
public ValueElement<string> IPAddress => this["ipAddress"] as ValueElement<string>;

[ConfigurationProperty("port", IsRequired = true)]
public ValueElement<int> Port => this["port"] as ValueElement<int>;
}

Now you can use your config in code like that:

var configuration = DataSourcesConfig.GetConfig();
var test1name = configuration.DataSources[0].Name.Value; // test1 as string
var test2name = configuration.DataSources[1].Name.Value; // test2 as string
var portForTest1 = configuration.DataSources[0].Port.Value // 12345 as int

Write a section in app.config file

Putting that information in the config-file is only one step to achieve what you're looking for.

Your <Example>-node is a custom section, that's unknown at that time. For enabling the ConfigurationManager to parse your section to an actual object at runtime, you'll have to define your section as a class deriving from ConfigurationSection:

public class ExampleSection : ConfigurationSection
{
[ConfigurationProperty("file", IsRequired = true)]
public string File
{
get
{
return this["file"];
}
set
{
this["file"] = value;
}
}

For a complete example, please have a look at this comprehensive MSDN-article.

Use App.config with a Custom Section shared between two different projects

Thanks @Alex Paven, your comment has helped me to solve this problem!

Here below there are the detailed steps of what I've done:

  1. I moved the 4 classes which handles the Windows service config file in a Class Library project (.NET Framework) called: DRS_CustomConfig.

  2. I changed the namespace of the 4 classes with the following value: DRS_CustomConfig and then I compiled the project.

  3. I linked the external library both in the Windows service project and in Windows Form application

  4. For each class of both projects which need to use the classes contained in the external library I inserted the following piece of code:

    using DRS_CustomConfig;
  5. In the App.config of the Windows service I changed the section element as follows:

Old

        <section name="sourceTabSection" 
type="DataReportingService.CustomSourceTabSection.SourceTabSection,
DataReportingService"/>

New

        <section name="sourceTabSection" 
type="DRS_CustomConfig.SourceTabSection, DRS_CustomConfig"/>

Custom section in App.Config, ConfigurationManager stops working

You have to use the tag <configSections> at the top in your app.config, for this case you should use the type AppSettingsSection

    <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="ImageFormatsINeed" type="System.Configuration.AppSettingsSection" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<appSettings>
<add key="overwriteBackupFiles" value="False"/>
<add key="path" value="c:\temp"/>
</appSettings>
<ImageFormatsINeed>
<add key="type1" value="width=180&height=180"></add>
<add key="type2" value="width=220&height=220"></add>
<add key="type3" value="width=500&height=500"></add>
</ImageFormatsINeed>
</configuration>

Then in your C# code:

NameValueCollection settings_section = ConfigurationManager.GetSection("ImageFormatsINeed") as NameValueCollection;
Console.WriteLine(settings_section["type1"]);


Related Topics



Leave a reply



Submit