A problem when collaborating on web.config file
The same applies to an app.config file, of course.
When working with web.config file, a problem arises once multiple developers are working on the same application. The config file may contain machine or environment specific settings, which are different between developer machines and target (development/test/staging/production) environments.
- I do not want to think about what to do with my config settings during development, because of process obligations. When I add a setting I add it, and there it ends. Optionally, I also add the setting values for all possible target environments.
- I do not want to notify other developers that I have added a setting. They need to receive it automatically
- I do not want to store settings in multiple places (eg. seperate xml's). I want one config file.
- I do not want to roll my own system, but make use of existing techniques of .NET and Visual Studio as much as possible.
- Settings in deploys need to be handled without much hassle.
On handling this problem, there are a few options.
Check-in the file
Check-in the file, overwrite each others settings, and try not to forget to not check in yourself.
Well, this is not really a solution. I've been here, this is exactly the problem that needs to be fixed, this causes lots of friction during development.
Don't check-in the file
Can't check-in the file? Let's have some self-control and don't check in our config changes. We know how long that's going to last. One moment of carelessness and the system is lost.
Ignore the file
We can tell our source control system to ignore the files. This way we don't have to be disciplined. Everyone can use their own setting values.
This solves the problem of not overriding each others settings, but introduces new problems.
How will other team members receive the setting?
How will you deploy your new settings to the target environments?
You could add an extra "central" configuration file, which can be used for deploys and consulted by other team members. But that causes the settings to be in 2 places which then needs to be maintained again.
The most elegant solution so far
Following is an approach that seems to be fixing all of these problems:
We have one single, checked-in and complete web.config file, developer setting overrides and target environment overrides for deploys. And we are only using built-in techniques.
Developer setting values for appSettings
The appSettings section provides an option to override settings in a separate file. Settings can be added to the central file and overridden in a separate file. Developer specific values can then be added to the separate file.
The contents of that file looks like:
<!-- PUT YOUR LOCAL DEV CONFIG OVERRIDES HERE -->
Developer setting values for connectionStrings
The connectionStrings configuration section does not have an attribute like file. However, there exists an attribute for any configuration section element:
This attribute does not allow specific settings to be overridden, but does allow putting a whole config section in another file.
You can then use it as follows:
<connectionStrings configSource="web.dev.connectionstring.config" />
And then put the whole section in a separate file.
What to check in?
The files can be arranged, so that there are template files for the developer files in a separate (solution) folder.
When a developer starts working on the project, he can copy the files from there into the Web project. The files are known in the project, so they will be indicated as "missing", until you copy-paste or create them.
These template files are checked in, obviously. The local version is not checked in.
These files do cause second versions of config files, which could be seen as friction. But since these files will remain empty, they need no management or maintenance at all.
How are deploys handled?
For deploys, we use Web Deploy and of course, for deploys we make use of the config transforms. The developer specific settings can be removed and the target environment settings can be put in place:
Below is an example of a config transform, which does the necessary actions to create a correct web.config for target environments:
Some words of explanation:
- RemoveAttributes(file): this transform is used to remove the file attribute from the appSettings section
- xdt:Transform="Replace" on connectionStrings: this will replace the whole connectionStrings section.
<!-- put regular transforms here -->
<add name="mainconnectionstring" connectionString="..." />
- This solution nicely extracts all developer setting overrides into other, not checked-in, files.
- There is a single, central, config file.
- The settings can be read without using any custom code.
- Deploys just work by using standard techniques of the framework.