Use XML includes or config references in app.config to include other config files’ settings

Yes, you can use the configSource attribute of the configuration block. All configuration blocks have this attribute – although it isn’t documented.

See this article, all the way at the bottom, appendix B. I’ve also pasted the relevant section below:

Appendix B: including external configuration files

Despite all the greatness to be found in .NET 2.0’s configuration features, there is one drawback. When working on a single project across multiple environments, managing configuration can become a nightmare. The process of managing multiple versions of a configuration file for multiple environments — i.e. development, testing, staging and production — at my current job involves manual comparisons of .config files whenever changes are deployed to one environment or another, with a manual merging process. I spent months trying to find a better way and eventually found one. Enter one of those oh-so beloved “undocumented” — or in this case, just poorly documented — features that Microsoft is so famous for: configSource. I only came across this little gem when I was digging through the .NET 2.0 configuration source code with Reflector, wonderful little tool.

Each configuration section, when parsed and loaded by the .NET configuration classes, is assigned a SectionInformation object. The SectionInformation object contains meta information about a configuration section and allows some management of how sections override each other when defined in a child config file (ASP.NET). For now, we will ignore the majority of what SectionInformation has to offer, save the ConfigSource property. By adding a configSource attribute to the root element of any ConfigurationSection, you can specify an alternate, external source from which the configuration settings will be loaded.

<!-- SomeProgram.exe.config -->
  <connectionStrings configSource="externalConfig/connectionStrings.config"/>

<!-- externalConfig/connectionStrings.config -->
  <add name="conn" connectionString="blahblah" />

In the configuration file above, the <connectionStrings> section has been sourced from a file called externalConfig/connectionStrings.config. All of the application’s connection strings will be loaded from the specified file. Now that the connection strings are loaded from an external resource, it is a relatively simple matter to create a connectionStrings.config file in each environment at the same relative location. Hence, the externalConfig/ part of the connectionStrings.config path. The beauty here is that we can define connection strings properly for each environment once. We do not have to worry about accidentally overriding those settings during a deployment where a config file was either merged improperly or not merged at all. This can be a huge boon when deploying changes in an application to a production environment, where it is critical that the correct database connection strings exist. The downfall of using the configSource attribute is that it requires all configuration settings to be placed in the external file. No inheritance or overriding is possible, which in some cases makes it useless. All external configuration files used with the configSource attribute must also reside in a relative child path to the main .config file. I believe this is in regards to security concerns with storing the file in a relative parent path in a web environment.

Something else to note is that the <appSettings> section has a better alternative to using configSource, called file. If you use the file attribute rather than configSource with the <appSettings> section, you can define settings in both the root .config file and in the referenced file. Settings from the root .config file may also be overridden in the referenced file, simply by adding something with the same key. Sadly, the file attribute is only available on the <appSettings> section and is not built into the configuration framework. It is possible to implement a similar attribute in your own configuration sections. This will be discussed in a future installment of advanced configuration topics, after several prerequisite installments ;).

Leave a Comment