<p>The web applications I develop often require co-dependent configuration settings and there are also settings that have to change as we move between each of our environments.</p>
<p>All our settings are currently simple key-value pairs but it would be useful to create custom config sections so that it is obvious when two values need to change together or when the settings need to change for an environment.</p>
<p>What's the best way to create custom config sections and are there any special considerations to make when retrieving the values?</p>

[{'answer_id': 2178, 'author': 'John Downey', 'author_id': 200, 'author_profile': 'https://Stackoverflow.com/users/200', 'pm_score': 2, 'selected': False, 'text': '<p>You can accomplish this with Section Handlers. There is a basic overview of how to write one at <a href="http://www.codeproject.com/KB/aspnet/ConfigSections.aspx" rel="nofollow noreferrer">http://www.codeproject.com/KB/aspnet/ConfigSections.aspx</a> however it refers to app.config which would be pretty much the same as writing one for use in web.config. This will allow you to essentially have your own XML tree in the config file and do some more advanced configuration.</p>\n'}, {'answer_id': 2219, 'author': 'Ishmaeel', 'author_id': 227, 'author_profile': 'https://Stackoverflow.com/users/227', 'pm_score': 4, 'selected': False, 'text': '<p>Quick\'n Dirty:</p>\n\n<p>First create your <strong>ConfigurationSection</strong> and <strong>ConfigurationElement</strong> classes:</p>\n\n<pre><code>public class MyStuffSection : ConfigurationSection\n{\n    ConfigurationProperty _MyStuffElement;\n\n    public MyStuffSection()\n    {\n        _MyStuffElement = new ConfigurationProperty("MyStuff", typeof(MyStuffElement), null);\n\n        this.Properties.Add(_MyStuffElement);\n    }\n\n    public MyStuffElement MyStuff\n    {\n        get\n        {\n            return this[_MyStuffElement] as MyStuffElement;\n        }\n    }\n}\n\npublic class MyStuffElement : ConfigurationElement\n{\n    ConfigurationProperty _SomeStuff;\n\n    public MyStuffElement()\n    {\n        _SomeStuff = new ConfigurationProperty("SomeStuff", typeof(string), "&lt;UNDEFINED&gt;");\n\n        this.Properties.Add(_SomeStuff);\n    }\n\n    public string SomeStuff\n    {\n        get\n        {\n            return (String)this[_SomeStuff];\n        }\n    }\n}\n</code></pre>\n\n<p>Then let the framework know how to handle your configuration classes in <strong>web.config</strong>:</p>\n\n<pre><code>&lt;configuration&gt;\n  &lt;configSections&gt;\n    &lt;section name="MyStuffSection" type="MyWeb.Configuration.MyStuffSection" /&gt;\n  &lt;/configSections&gt;\n  ...\n</code></pre>\n\n<p>And actually add your own section below:</p>\n\n<pre><code>  &lt;MyStuffSection&gt;\n    &lt;MyStuff SomeStuff="Hey There!" /&gt;\n  &lt;/MyStuffSection&gt;\n</code></pre>\n\n<p>Then you can use it in your code thus:</p>\n\n<pre><code>MyWeb.Configuration.MyStuffSection configSection = ConfigurationManager.GetSection("MyStuffSection") as MyWeb.Configuration.MyStuffSection;\n\nif (configSection != null &amp;&amp; configSection.MyStuff != null)\n{\n    Response.Write(configSection.MyStuff.SomeStuff);\n}\n</code></pre>\n'}, {'answer_id': 2928, 'author': 'andynil', 'author_id': 446, 'author_profile': 'https://Stackoverflow.com/users/446', 'pm_score': 7, 'selected': True, 'text': '<p><strong>Using attributes, child config sections and constraints</strong></p>\n\n<p>There is also the possibility to use attributes which automatically takes care of the plumbing, as well as providing the ability to easily add constraints.</p>\n\n<p>I here present an example from code I use myself in one of my sites. With a constraint I dictate the maximum amount of disk space any one user is allowed to use.</p>\n\n<p>MailCenterConfiguration.cs:</p>\n\n<pre><code>namespace Ani {\n\n    public sealed class MailCenterConfiguration : ConfigurationSection\n    {\n        [ConfigurationProperty("userDiskSpace", IsRequired = true)]\n        [IntegerValidator(MinValue = 0, MaxValue = 1000000)]\n        public int UserDiskSpace\n        {\n            get { return (int)base["userDiskSpace"]; }\n            set { base["userDiskSpace"] = value; }\n        }\n    }\n}\n</code></pre>\n\n<p>This is set up in web.config like so</p>\n\n<pre><code>&lt;configSections&gt;\n    &lt;!-- Mailcenter configuration file --&gt;\n    &lt;section name="mailCenter" type="Ani.MailCenterConfiguration" requirePermission="false"/&gt;\n&lt;/configSections&gt;\n...\n&lt;mailCenter userDiskSpace="25000"&gt;\n    &lt;mail\n     host="my.hostname.com"\n     port="366" /&gt;\n&lt;/mailCenter&gt;\n</code></pre>\n\n<p><strong>Child elements</strong></p>\n\n<p>The child xml element <em>mail</em> is created in the same .cs file as the one above. Here I\'ve added constraints on the port. If the port is assigned a value not in this range the runtime will complain when the config is loaded.</p>\n\n<p>MailCenterConfiguration.cs:</p>\n\n<pre><code>public sealed class MailCenterConfiguration : ConfigurationSection\n{\n    [ConfigurationProperty("mail", IsRequired=true)]\n    public MailElement Mail\n    {\n        get { return (MailElement)base["mail"]; }\n        set { base["mail"] = value; }\n    }\n\n    public class MailElement : ConfigurationElement\n    {\n        [ConfigurationProperty("host", IsRequired = true)]\n        public string Host\n        {\n            get { return (string)base["host"]; }\n            set { base["host"] = value; }\n        }\n\n        [ConfigurationProperty("port", IsRequired = true)]\n        [IntegerValidator(MinValue = 0, MaxValue = 65535)]\n        public int Port\n        {\n            get { return (int)base["port"]; }\n            set { base["port"] = value; }\n        }\n</code></pre>\n\n<p><strong>Use</strong></p>\n\n<p>To then use it practically in code, all you have to do is instantiate the MailCenterConfigurationObject, this will <strong>automatically</strong> read the relevant sections from web.config.</p>\n\n<p>MailCenterConfiguration.cs</p>\n\n<pre><code>private static MailCenterConfiguration instance = null;\npublic static MailCenterConfiguration Instance\n{\n    get\n    {\n        if (instance == null)\n        {\n            instance = (MailCenterConfiguration)WebConfigurationManager.GetSection("mailCenter");\n        }\n\n        return instance;\n    }\n}\n</code></pre>\n\n<p>AnotherFile.cs</p>\n\n<pre><code>public void SendMail()\n{\n    MailCenterConfiguration conf = MailCenterConfiguration.Instance;\n    SmtpClient smtpClient = new SmtpClient(conf.Mail.Host, conf.Mail.Port);\n}\n</code></pre>\n\n<p><strong>Check for validity</strong></p>\n\n<p>I previously mentioned that the runtime will complain when the configuration is loaded and some data does not comply to the rules you have set up (e.g. in MailCenterConfiguration.cs). I tend to want to know these things as soon as possible when my site fires up. One way to solve this is load the configuration in _Global.asax.cx.Application_Start_ , if the configuration is invalid you will be notified of this with the means of an exception. Your site won\'t start and instead you will be presented detailed exception information in the <a href="http://www.codinghorror.com/blog/images/yellow-screen-of-death-large.png" rel="noreferrer">Yellow screen of death</a>.</p>\n\n<p>Global.asax.cs</p>\n\n<pre><code>protected void Application_ Start(object sender, EventArgs e)\n{\n    MailCenterConfiguration.Instance;\n}\n</code></pre>\n'}, {'answer_id': 545973, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>The custom configuration are quite handy thing and often applications end up with a demand for an extendable solution.</p>\n\n<p>For .NET 1.1 please refer the article <a href="https://web.archive.org/web/20211027113329/http://aspnet.4guysfromrolla.com/articles/020707-1.aspx" rel="nofollow noreferrer">https://web.archive.org/web/20211027113329/http://aspnet.4guysfromrolla.com/articles/020707-1.aspx</a></p>\n\n<p>Note: The above solution works for .NET 2.0 as well.</p>\n\n<p>For .NET 2.0 specific solution, please refer the article <a href="https://web.archive.org/web/20210802144254/https://aspnet.4guysfromrolla.com/articles/032807-1.aspx" rel="nofollow noreferrer">https://web.archive.org/web/20210802144254/https://aspnet.4guysfromrolla.com/articles/032807-1.aspx</a></p>\n'}, {'answer_id': 18899141, 'author': 'LordHits', 'author_id': 8088, 'author_profile': 'https://Stackoverflow.com/users/8088', 'pm_score': 3, 'selected': False, 'text': '<p>There\'s an excellent <a href="http://msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx" rel="noreferrer">example on MSDN</a> using <code>ConfigurationCollection</code> and .NET 4.5 for custom sections in web.config that has a list of config items.</p>\n'}, {'answer_id': 42043653, 'author': 'Mike', 'author_id': 6830841, 'author_profile': 'https://Stackoverflow.com/users/6830841', 'pm_score': 2, 'selected': False, 'text': '<p>The most simple method, which I found, is using <a href="https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.appsettings%28v=vs.110%29.aspx?f=255&amp;MSPPError=-2147217396" rel="nofollow noreferrer">appSettings section</a>.</p>\n\n<ol>\n<li><p>Add to Web.config the following:</p>\n\n<p><pre><code>&lt;appSettings>\n    &lt;add key="MyProp" value="MyVal"/>\n&lt;/appSettings>\n</pre></code></p></li>\n<li><p>Access from your code</p>\n\n<p><pre><code>NameValueCollection appSettings = ConfigurationManager.AppSettings;\nstring myPropVal = appSettings["MyProp"];\n</pre></code></p></li>\n</ol>\n'}]
['https://Stackoverflow.com/questions/2155', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/371/']