Editor’s note: The following post was written by Visual Studio and Development Technologies MVP Subodh Sohoni as part of our Technical Tuesday series with support from his technical editor, Visual Studio and Development Technologies MVP Gouri Sohoni.
When we use Release Management to deploy an application from Visual Studio Team Services to Azure, we come across a typical issue of deploying environment specific configurations. For example we may have a testing environment and production environment. The database servers in both of these may be different. We provide the connection string in such a way that it points towards the database in which it is presently deployed. We cannot have a manual step in the release to change the connection string as appropriate. It needs to be done by the automated process of the release management. Let us find out a solution for this issue. For basic information about how to deploy a web application from VSTS to an Azure VM please read the article “Continuous Integration and Deployment of a Web application from Visual Studio Team Services to a Azure VM” at http://www.dotnetcurry.com/visualstudio/1276/continuous-integration-deployment-from-vsts-azure-vm.
What we need to do logically is to use a variable in the configuration file. Naturally, for an ASP.NET web application that configuration file is web.config. This variable will have an initial value which is just a dummy value. That value of the variable can be replaced by the actual value as appropriate for the environment in which the application is being deployed. If we were using WebDeploy that internally uses the tool MsDeploy.exe, then we could have overridden the value in web.config during the deployment. My intention is to do it without WebDeploy as that seems to me a heavy gun for small target. This replacement will have to be done just before or as part of the deployment. Replaced value will be different for each environment. We will need to keep a template configuration file that will contain the variable in the appSettings section. This template will be used for creating actual web.config file after replacement of the value of that variable. We do not want the template itself to be overwritten as part of the deployment. We will use that template file repeatedly for as many environments as we need to do the deployment on.
We will begin by creating such a template and conveniently call it web.config.template. We will keep it in the same folder where the web.config is to be located, for the example we will keep it at the root folder of the web application.
For the variables that need to be replaced, we need an access to the values of those custom variables in the process of deployment using Release Management. This access to values for replacement is provided by a process called tokenization. For tokenization of the custom variable values, we will have to use a custom task called Tokenizer in the workflow of the release. It tokenizes the variable in web.config which then can be transformed. Tokenizer needs the initial values of the custom variable in a specific format. It should be in the key – value pair where value is necessarily “__key__” as shown below.
To install the tokenizer we will first need node.js with npm packager installed on our machine. Follow this process to install and use Tokenizer.
Download and install node.js on your machine if it is not present. It also installs npm package loader.
Download tokenizer from https://github.com/openalm/VSOtasks. It comes as a .zip file. Unzip it.
Open command prompt and change directory to the folder “Tokenizer\x.x.x” in the unzipped folder.
From that folder run the command npm install -g tfx-cli to install the command line tool that can upload the tokenizer task.
Now execute a command tfx login –authType basic
Give your alternate credentials when asked for
Finally run the command tfx build tasks upload –task-path ./
This adds the tokenizer task in the available tasks for release management.
Using the installed Tokenizer
In the Release definition add the task of tokenizer above the Azure Copy Files task.
For the Source filename provide the value - $(System.DefaultWorkingDirectory)\WebApp4/Publish/WebApplication4/web.config.template Replace WebApp4 and WebApplication4 with your build name and application name.
For the Destination filename provide the value - $(System.DefaultWorkingDirectory)\WebApp4/Publish/WebApplication4/web.config
We will create the variables in the Release Definition that are scoped to the environment. Click the context menu expander (… in the tile of the environment). From the context menu select the Configure Variables.
Now add the variable for connection string as named in the web.config.template file and their environment specific values.
For the Azure File Copy task ensure that the machine name filter contains the value of the VM that is earmarked for testing. In my case it was RMDemoServer.
Similarly add the environment for Production. It should also have the same tasks and variable named ConStr. The only difference is ConStr variable will have the value of DBS2 as the data source and RMDemoServer2 as the filter for machine name in the Azure File Copy task.
Save the release definition. Create a new release and deploy it.
On the RMDemoServer VM in the testing environment, we will find the web.config file under the c:\inetpub\wwwroot folder. It has the ConStr key that has the value as configured in the ConStr variable of Testing environment.
On the RMDemoServer2 VM in the Production environment also we will find the web.config file under the c:\inetpub\wwwroot folder. It has the ConStr key that has the value as configured in the ConStr variable of Production environment.
In this short article we have seen how to write the environment specific configuration file when we are deploying to two different environments that require different configurations.
About the author
Subodh is process consultant and corporate trainer. He is an engineer with post-graduation in Aircraft Production from IIT, Madras. He has overall 30 years of experience in production, sales, marketing, networking, software development, team building and process optimization. His specialization of subject for the last 10 years is Application Lifecycle Management, Visual Studio Team Services and Team Foundation Server. In a addition to being awarded as a Microsoft – VS ALM, MCSD – ALM, he is a Microsoft Certified Trainer He has conducted more than 300 corporate trainings and consulting assignments. He is a Professional SCRUM Master. He guides teams to become Agile and implement SCRUM.