I love WebDeploy – I have ever since I read Scott Hanselman’s post “Web Deploy Made Awesome: If You’re Using XCopy, You’re Doing It Wrong”. Whenever I’m helping teams that build web applications improve their ALM processes, invariable I end up moving them onto Web Deploy. Not only is it an easier and cleaner way to deploy, but you get the bonus of being able to manage configuration files (Web.config) in your project.
Config as Code
Maturing in ALM means that you need to head towards continuous deployment. You need to be able to deploy your application with a single click of a button. However, one challenge with this is managing configurations. How do you manage Web.config files in dev, UAT and Production environments? Do you find yourself copying config files out the way before you deploy? That’s BAD. You should be managing your configs as if they were code. They need to be source controlled.
Fair enough, I hear you say. So you’ll just copy all your config files from all your servers into a folder and manage them from there. Better – but still lots of pain. A far better approach is to use config transforms.
Config transforms came into web applications in VS 2010. With the latest release of VS 2013, not only are they also available for web sites (NOTE: please don’t use websites – always use web applications!) but you can new preview your transforms from VS and there’s now support for profile-specific transforms.
Let’s have a look at a config transform in a newly created MVC web application. You can see that the Web.config file expands to show 2 other files – one per project configuration:
If you add project configurations, then you can right-click the Web.config and select “Add config Transforms” and VS will create a new transform file for you.
Let’s have a look at the Web.Release.config (I’ve removed the comments that are auto-generated):
You can see that in the
This is all existing “2012” stuff. What’s new in the latest release?
Preview and Profile Specific Transforms
You can now preview your transform by right-clicking on the transform file (Web.Release.config, for example) and selecting “Preview Transform”. This immediately shows a diff – the original Web.config on the left and the transformed config on the right:
Now you can debug your transforms!
So let’s imagine you have a UAT environment. You want to publish your site, so you create a new project configuration called UAT. You then copy the release transforms and put in your UAT connection strings and so on. After doing some testing in UAT, you realize that you actually need to debug, so you’ll have to update your Web.UAT.config file again, or create a UAT-DEBUG project configuration. Soon you’ll get lots of project configurations, and that’s just a mess.
However, you can now create a profile-specific transform on top of the project configuration transforms! Let’s create a publish profile. I’ll right-click the web project and select “Publish”. I’ll create a new profile called “UAT-Debug” and give it whatever settings I need to. On the “Configuration” page, I’ll change the configuration from Release to Debug.
Then I’ll click on “Close” to save the profile without publishing. That will create a pubxml file for me. I’ll repeat the process and create a publish profile called “UAT-Release”. Looking under the Properties of my project I’ll see the pubxml files:
Now I can right-click a pubxml and select “Add Config Transform” – which creates a new transform for me that’s tied to this publish profile.
Let’s insert an attribute in both of the new config files:
I’ve also removed the debug attribute from the compilation tag on the UAT-Release config and removed that transform from the debug one:
Now when I right-click Web.UAT-Release.config and select “Preview Transform” I can see the diff. Note that the right-hand file tells me that it has actually applied 2 transforms: first the Release transform (since the profile specifies Release for the project configuration) and secondly the Web.UAT-Release.config transforms themselves.
If you’re using Release Management, don’t forget to check out my post about how to use config transforms for parameterizing releases!