Ever felt a need for different
configuration files for different environments? This is a very common
requirement where you want your configurations to adapt based on the
environment it is built for. Let’s see how we have done it for different types
of projects (web and client). What is available out of the box and what’s not?
Scenario
We have three different
environments for which we change the environment specific values in the
configuration file and fire the build. That’s sounds good until we ran into
issues described in next section.
What is the issue?
There were two issues that we
came across:
1.
We have
different projects which have environment specific configuration, whenever we
need a build for new environment we have to manually change the values at tons
of places which is cumbersome and error-prone. It will become impossible to do
once more and more projects are added which have environment specific data. To
add to the pain more environments are in place for which we need to build for every
deployment cycle.
2.
For web
projects, config transformation is supported out of the box but for client
applications, config transformation is not supported at all. In Step 6 of “Code
and Steps” below, we have followed different approaches to address this issue.
How to resolve the issue?
While resolving the issue you need to identify the environment specific data. Some of the environment
specific data that we generally have is server urls, services bindings,
connection strings, etc. Try to keep them in the config files of the projects.
You can change the value during build based on the target build environment.
For accomplishing this while
building, you can have different build configuration for different environments.
Taking into account say, you have two different environments for QA and
Production. You need to do the following:
1.
You need to
make environment specific build configuration and add that to the solution.
2.
Update
configuration in each project which has value that changes with environment.
3.
For picking up
the specific configuration in the code from config files you can :
a.
Either
transform config files based on the build configuration selected.
b.
Or pick
altogether a different config file every time based on the build configuration
selected. (You need to do this as client applications do not support config
transformation.)
Code and Steps for implementing the solution
First you need to create
environment specific configuration data. For accomplishing this while building,
we can have different build configuration for different environments. Say, you have two different environments for QA and Production. You need to do the
following:
1.
Right click on
Solution and Select “Configuration Manager” :
2.
In
Configuration Manager, select Active Solution Configuration as “New” :
NOTE: You need to modify Active Solution Platform
based on your environment settings.
3.
In New
Solution Configuration dialog, give the name for the configuration, say
“QADeploy”. Just copy the settings from any configuration you think is the
similar to the current one and then you can change the values of properties
opening the project file. Similarly make configuration for production, say
“ProdDeploy”.
4.
Now if you
open the project file, you can see configuration section added, something like
this:
NOTE
: The properties may differ based on your Visual Studio settings.
5.
You can add
more properties or can modify existing ones based on the environment specific
needs.
6.
Now based on
the build configuration you can either transform config files or you can include
all together a different config file for different configuration. Let’s see one
by one how you can accomplish this.
a. First Approach : Config
Transformation
This
approach is useful in case of Web.config which supports config transformation
out of the box. Follow the steps listed below:
i. In Solution Explorer, right-click the Web.config file and then click Add Config Transforms.
ii. Open the transform file for the build configuration
that you want to work with :
iii. Edit the transform file to specify the changes that
should be made to the deployed Web.config file when you deploy by using that
build configuration.
The following example shows how to
use the Match locator and the SetAttributes transform attribute. The Match locator attribute identifies the add element in the connectionStrings section as the element to change. The SetAttributes transform attribute specifies that this element's connectionString attribute should be changed to
"NewEnvironmentSQLServer".
For more information about how to write transform files, see Web.config Transformation
Syntax for Web Application Project Deployment.
iv. Save and close the transform file.
b. Second Approach : Including
different config based on Build Configuraiton
This
approach is particularly useful in case of App.config which does not support
config transformation. Follow the steps listed below for including different
App.config for different build configuration
i. Add a folder named Configs in your project.
ii. Add a folder for each environment under this folder.
iii. Copy your App.config from project and add it in each of
the folder created.
iv. Make changes to the config file based on the
environment, e.g. - changing the database connection strings, etc.
v. REMOVE the following code from the project file:
<None Include="App.config" />
<None Include="Configs\Prod\App.config" />
<None Include="Configs\QA\App.config" />
vi. ADD the following code to project file for different
configurations:
<ItemGroup Condition="
'$(Configuration)|$(Platform)' == Debug|AnyCPU' ">
<None Include="App.config" />
</ItemGroup>
<ItemGroup Condition="
'$(Configuration)|$(Platform)' == Release|AnyCPU' ">
</ItemGroup>
<ItemGroup Condition="
'$(Configuration)|$(Platform)' == 'QADeploy|AnyCPU' ">
<None Include="Configs\QA\App.config" />
</ItemGroup>
<ItemGroup Condition="
'$(Configuration)|$(Platform)' == 'ProdDeploy|AnyCPU' ">
<None Include="Configs\Prod\App.config" />
</ItemGroup>
NOTE
: Platform may differ, it can be AnyCPU, x86, x64, etc. based on your settings.
Basically in the code above, its defined from which folder to pick App.Config
based on the BuildConfiguration property value.
7.
You are good
to build your solution using the build configuration and your environment
specific configuration will automatically be picked according to the
configuration specified.