Search code examples
powershellxsltvisual-studio-2015tfs-2015continuous-deployment

Environment-specific configuration in app/web.config when implementing continuous deployment


TL;DR;

How to manage environment-specific settings in app.config/web.config with Visual Studio & TFS 2015 when implementing continuous deployment?

Full question

I am trying to implement continuous deployment for my C# Visual Studio 2015 solution using the built-in feature in TFS 2015. I'm currently wondering how should I proceed to setup settings in my configuration files that are environment-dependent (typically, DB connection string).

I have basically 4 different environments: production, preproduction, UAT and integration. I'm not deploying to Azure or the cloud. Everything is on premises on servers within my company.

I've tried to implement the solution proposed on this link but unless I misunderstood something, I feel that it means I would have to also tokenize my web.config and app.config inside my Visual Studio solution. I want to avoid that as I want to keep my - and my team mates' - experience as usual as possible. I don't want us having to modify yet another file to manage our configuration settings.

I thought of using XML transform also, that would be triggered by a Powershell task during the deployment. Basically, I leave my config files as is and that task modifies the config files when triggered (as suggested on this link). But ideally, I'd like to use the built-in environment variables of the release. Additionally, that would mean my transform file would be checked-in as part of my solution. If I need to change it, I need to run a new build/deployment. I want to avoid that.

So no solution is fully satisfying. I was wondering if some other tools or libraries were available that could do the job. I couldn't find anything. If there's nothing I guess I could come up with something with a Powershell task but if I can avoid reinventing the wheel...

Last thing, I thought I could create in Visual Studio a new configuration based on the "Release" one that I would name - say - "Deployment". Then I'd use XML Transform on this configuration only to tokenize the configuration file and leave Debug and Release as is. In my TFS build I would use this configuration in order to deploy the tokenized configuration file as an artifact that I could finally update with a a Powershell script and environment variables like in the first link above. But it seems too complex and involves too many things. I'm sure there is something more simple that can be done.

There is this solution also but it means 1 environment = 1 build. I absolutely want to avoid that. I want 1 build = deploy everywhere.


Solution

  • If you want some settings like the DB connection string in app.config/web.config be changed in different release environment when deploy, you could download this Release Management Utility tasks extension and install it for your TFS collection. Use the Tokenize with XPath/Regular step to change the corresponding value.

    In this step, it provides many methods to replace the value in a file. For most methods, you need to change the connecting string like: _ConnectingValue_. If you don't want to add this symbol(_), you could use the method below:

    1. Your web.config file may like this:

    Code:

      <?xml version="1.0" encoding="utf-8"?>
        <configuration>
          <appSettings>
            <add key="TestKey1" value="Old Value" />
          </appSettings>
        </configuration>
    
    1. Create a .json file:

    Code:

    {
          "Default Environment":{
              
              "ConfigChanges":[
                 {
                    "KeyName":"/configuration/appSettings/add[@key='TestKey1']",
                    "Attribute":"value",
                    "Value":"New value"
                 }
              ]
           }
        }
    
    1. Then your old value will be changed to new value.

    Result:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
        <add key="TestKey1" value="New value" />
      </appSettings>
    </configuration>
    

    To know more about this step:

    1. Using Tokenization for Builds/Releases in vNext/TFS 2015

    2. VS 2015 Release Management Tokenize XPath/Regular expressions not working