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
.configfiles 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
SectionInformationobject 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
ConfigSourceproperty. By adding a
configSourceattribute 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 --> <configuration> <connectionStrings configSource="externalConfig/connectionStrings.config"/> </configuration> <!-- externalConfig/connectionStrings.config --> <connectionStrings> <add name="conn" connectionString="blahblah" /> </connectionStrings>
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.configfile in each environment at the same relative location. Hence, the
externalConfig/part of the
connectionStrings.configpath. 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
configSourceattribute 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
configSourceattribute must also reside in a relative child path to the main
.configfile. 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
.configfile and in the referenced file. Settings from the root
.configfile 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 ;).