setting app.config for different environments

Imagine the following scenario: You have a project that you just developed in your local machine and want to deploy it into the CI (Continuous Integration) and approval environments. In this project, there is a configuration file (app.config) that contains a few settings, for instance, connection strings and log file directory.

Quite common isn’t it? So, how do you handle with the annoying issue of changing your app.config file for all these environments?

Editing the configuration file in each environment doesn’t seem to be a smart solution. During the development, we can add further settings into the app.config. Updating the config file later (during the deployment) for every environment is a hard and unreliable manner to do this because we can miss some changes.

Another choice that I’ve seen consists in having a copy in your project for each environment. Well, this is much better. We will have app.config, app.config.ci, app.config.approval and app.config.production to satisfy our environments. So, whenever we need to add or change any settings, we can edit all these config files during the development phase. To deploy, just rename the correct file to app.config and that’s it. But the problem that I see in this solution is that our SCM will run crazy with all the renamings.

For example: rename app.config to app.config.local and app.config.ci to app.config. SCM will tell you that app.config has been modified, app.config.local has been created and app.config.ci has been deleted. What a mess!

Another issue of this solution is that it doesn’t help us when we want automatated deployment. It depends on manual editing of the config files or a dependency on a script to do the job.

To avoid these painful processes, we can use the project’s configurations and after build tasks set in .csproj file. I will explain in the following steps:

1st Step

1st Step

As default, Visual Studio creates two project configurations: Debug and Release. We’re going to add a configuration for each environment, assuming that both default configurations applies to our local environment. So, let’s create CI, Approval and Production configurations.

  1. In your Visual Studio, go to the “Solution Configurations” combobox and click “Configuration Manager…”
  2. In “Active solution configuration” combo box select “<New…>”
  3. In the popup window, fill the “Name” field with your environment name and select Release in “Copy settings from” combobox. Check “Create new project configurations” if it is not checked.
  4. Repeat this process for all environments.

At the end, you should have something like this:

Set of solution configurations

2nd Step

2nd Step

Next, let’s create the copies of our App.config files. For this, we will name all the copies as {Configuration}.config. So, in my example, I’ll have Approval.config, CI.config, Production.config.

App.config copies

Let’s change the connection string values from the files.

App.config settings:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <add name="applicationConnection" connectionString="Data Source=localServer..." />
  </connectionStrings>
</configuration>

Approval.config settings:

<configuration>
  <connectionStrings>
    <add name="applicationConnection" connectionString="Data Source=approvalServer..." />
  </connectionStrings>
</configuration>

CI.config settings:

<configuration>
  <connectionStrings>
    <add name="applicationConnection" connectionString="Data Source=ciServer..." />
  </connectionStrings>
</configuration>

Production.config settings:

<configuration>
  <connectionStrings>
    <add name="applicationConnection" connectionString="Data Source=productionServer..." />
  </connectionStrings>
</configuration>

3rd Step

3rd Step

Finally, we will edit the .csproj file to add the AfterBuild task to replace the App.config file according to the configuration set on the build.

  1. Right click in your project and select “Unload Project”
  2. Right click “ProjectName(unavailable)” and select “Edit ProjectName.csproj”
  3. In the end of the file, add the next lines:

    <Target Name="AfterBuild" Condition="'$(Configuration)' == 'CI' or '$(Configuration)' == 'Production' or '$(Configuration)' == 'Approval' ">
        <Delete Files="$(TargetDir)$(TargetFileName).config" />
        <Copy SourceFiles="$(ProjectDir)$(Configuration).config" DestinationFiles="$(TargetDir)$(TargetFileName).config" />
    </Target>

Observe that these lines says: “After build, if configuration is ‘CI’ or ‘Production’ or ‘Approval’, delete output config file and copy {configuration}.config file into output file.”

After building using all configurations, you should have an output directory for each configuration in your bin folder. Check the config files and you should see the differences among them.

And that’s all! I hope you enjoyed this guide and starts to use it to build and deploy your projects with no worries regarding configuration files. C ya soon!

Tags: , , , ,

7 People have left comments on this post



» anahimself said: { Oct 13, 2009 - 06:10:55 }

Nice tip, im just wondering on how to use it within the setup project too (it always package the config file app.config)

» yoga said: { Nov 1, 2009 - 02:11:00 }

This is great. I have been looking for this kind of solution.
Is this going to work for web.config also??

» Andreas said: { Nov 2, 2009 - 12:11:13 }

this does not workwith VS MSI Installers. The installation ends up with the original app.config file

» Marc said: { Nov 25, 2009 - 10:11:44 }

Anahimself, i do the basically the same thing but in the PRE build event. Since the app.config file will be set before the compliation and the packaging, it will always be correct in your package.

» From Mars said: { Dec 1, 2009 - 08:12:13 }

Thanks - just what I was looking for.

The only side-effect of this is that if you’re not doing a straight xcopy deployment, the app.config is no longer added to the setup and deployment project output - anyone know how to resolve this?

» Stoffel said: { Mar 18, 2010 - 11:03:05 }

I am currently facing the same problem Mars is, how do you get the app.config from the Production Build to be the one that’s used for the deployment output?