.NET Configuration (app.config/web.config/settings.settings)
Any configuration that might differ across environments should be stored at the machine level, not the application level. (More info on configuration levels.)
These are the kinds of configuration elements that I typically store at the machine level:
- Application settings
- Connection strings
- retail=true
- Smtp settings
- Health monitoring
- Hosting environment
- Machine key
When each environment (developer, integration, test, stage, live) has its own unique settings in the c:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG directory, then you can promote your application code between environments without any post-build modifications.
And obviously, the contents of the machine-level CONFIG directory get version-controlled in a different repository or a different folder structure from your app. You can make your .config files more source-control friendly through intelligent use of configSource.
I've been doing this for 7 years, on over 200 ASP.NET applications at 25+ different companies. (Not trying to brag, just want to let you know that I've never seen a situation where this approach doesn't work.)
This might help some people dealing with Settings.settings and App.config: Watch out for GenerateDefaultValueInCode attribute in the Properties pane while editing any of the values in the Settings.settings grid in Visual Studio (Visual Studio 2008 in my case).
If you set GenerateDefaultValueInCode to True (True is the default here!), the default value is compiled into the EXE (or DLL), you can find it embedded in the file when you open it in a plain text editor.
I was working on a console application and if I had defaulted in the EXE, the application always ignored the configuration file placed in the same directory! Quite a nightmare and no information about this on the whole Internet.
There is a related question here:
Improving Your Build Process
Config files come with a way to override the settings:
<appSettings file="Local.config">
Instead of checking in two files (or more), you only check in the default config file, and then on each target machine, you put a Local.config, with just the appSettings section that has the overrides for that particular machine.
If you are using config sections, the equivalent is:
configSource="Local.config"
Of course, it's a good idea to make backup copies of all the Local.config files from other machines and check them in somewhere, but not as a part of the actual solutions. Each developer puts an "ignore" on the Local.config file so it doesn't get checked in, which would overwrite everyone else's file.
(You don't actually have to call it "Local.config", that's just what I use)
From what I am reading, it sounds like you are using Visual Studio for your build process. Have you thought about using MSBuild and Nant instead?
Nant's xml syntax is a little weird but once you understand it, doing what you mentioned becomes pretty trivial.
<target name="build">
<property name="config.type" value="Release" />
<msbuild project="${filename}" target="Build" verbose="true" failonerror="true">
<property name="Configuration" value="${config.type}" />
</msbuild>
<if test="${config.type == 'Debug'}">
<copy file=${debug.app.config}" tofile="${app.config}" />
</if>
<if test="${config.type == 'Release'}">
<copy file=${release.app.config}" tofile="${app.config}" />
</if>
</target>