Simple Config Transforms in Visual Studio 2010

If you’ve worked on the Microsoft ASP.NET platform for any length of time, in an environment where you had to manage deployment of your application across multiple servers, then you’ve probably stared at .config files until your head pounds. In the past we often managed this by keeping multiple copies of each .config and using pre-build events to copy the right one to the right place based on the active configuration. Recently my colleague Erez clued me in to the fact that Microsoft had stepped up and offered a solution in Visual Studio 2010 called “config transformations.”

Config transformations are essentially a set of rules, similar to an XSLT in intent, if not in syntax, that replace or transform the content of specific nodes in the .config XML when the site is published. The full capability is quite powerful, but I am going to ignore 90% of it here. If you want to understand the whole thing there is a useful post on the Visual Web Team Developer blog. It’s very interesting stuff, but my favorite line was the one that began, “Simplest Approach: If you do not mind replicating the entire web.config file in web.staging.config then you can certainly do so…” Bingo! I may take advantage of all the neato matching rules later. For now I’m happy if I can achieve what we do now without requiring script to be created and maintained in a pre-build event.

Fortunately this is dead simple to do. The first step will be to create the transforms. The idea is that you have a base configuration named web.config, and one or more transforms that are applied to it when publishing under specific configurations. If you’re starting with a new web app then transforms for the default “Debug” and “Release” configurations will be created for you. You will find them as file nodes under web.config in the Solution Explorer, similar to the way code behind and designer files are handled. If, like us, you have a solution that predates VS2010 and want to start using config transforms, here’s what you do:

First, make sure you have your configurations set up. We usually have local (Dev), Test, and Production configurations on web apps. Right-click the existing web.config file in Solution Explorer and click “Add Config Transforms.”

config_example2

Visual Studio will add transforms for any existing configuration that doesn’t already have one. In this simple example the result is two new files: Web.Debug.config and Web.Release.config. Here’s what it should look like after you finish:

config_example3

The next step is to delete one of them. Why? Well, recall that these are transforms. They change the base .config so that it will work in another environment. Which config doesn’t need to be transformed? The web.config that you use to run locally. What I like to do is modify the existing, or default Web.config so that it is set up to work in local debug situations, and then use transforms to modify it when the app runs in other environments. So in the example above you would get rid of Web.Debug.config, modify Web.config for local debugging, and modify the transform in Web.Release.config to work in the production environment. Here’s a simple Web.config that I will use to illustrate the rest of the example:

<?xml version="1.0"?>
<configuration>
	<appSettings>
		<add key="baseUrl" value="http://localhost:32767" />
	</appSettings>
	<connectionStrings>
		<add name="SiteDB" connectionString="server=localhost;database=SiteDB;uid=user;pwd=password"/>
	</connectionStrings>
</configuration>

As you can see this is set up for local debugging. Now for the release config. If you open up one of the transform files in the editor you’ll notice that it just contains an empty configuration node, along with some additional namespace information. Since we’re taking the simple route and swapping the entire file, the next thing to do is copy the contents of the configuration node from Web.Config to Web.Release.Config and modify it to work in the release environment. We also have to add the attribute that tells the transform tool to swap out the entire configuration node. Here”s what the completed file looks like:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform" xdt:Transform="Replace">
	<appSettings>
		<add key="baseUrl" value="http://www.mysite.com" />
	</appSettings>
	<connectionStrings>
		<add name="SiteDB" connectionString="server=proddbserver;database=SiteDB;uid=user;pwd=password"/>
	</connectionStrings>
</configuration>

Note the additional namespace attribute on the configuration node. That namespace contains the element and attribute definitions used to define the transformation rules. The template will add this for you when it creates the files. The second attribute on the configuration node is one we need to add manually. The attribute xdt:Transform=”replace” tells the tool to replace the entire contents of a node in the base config with the contents of the same node in the transform. Since we placed this rule on the root configuration node, the entire contents of the config will get pasted in when we publish.

And that’s pretty much it. Once you have this set up the transform will be applied when you publish the site under a named configuration for which a transform exists. One thing to note, which confused me for a couple of minutes, is that the transforms are not applied on a simple local build. If you want the transform to run without publishing you apparently have to add a custom task to your project file and then call it from an event. This decision doesn’t really make sense to me, but I haven’t taken the time to research it and see why they did it this way. Fortunately all my local builds are under my “Dev” configuration, which is handled by the base Web.config, so this doesn’t really cause me an issue. When I publish to test or production the transforms run, and everything works great.

A Sliding Number Puzzle in JQuery

I’ve never really been a huge javascript fan. I learned to program using an interpreted, weakly-typed language called BASIC. It was fun, interactive, stream-of-consciousness, creative, and a great way to learn the, um, basics. It was also pretty hard to write big, complicated programs in it. I happened to learn the language back in the mid-70’s on an HP3000 mainframe. We had access to two CRT and two teletype terminals. I recall that there was a pecking order in the student computer room, and it was awhile before I worked my way up to getting time on a CRT. Up to that point I had to print out every run and save my programs on punch tape, so my efforts were somewhat confined. Once on the CRT I began to scale up, and one of my aspirations was to write a space game. But this was pre-procedural BASIC, all gotos and gosubs, and it was only a few ten thousands of lines long when its complexity outstripped my structural abilities and it collapsed into a heap.

I still have a prejudice in favor of strongly-typed, compiled languages, but I also think scripting is the future of the bulk of development. And it’s still fun. Working with javascript or php today is the equivalent, for me, of loading up the BASIC interpreter and making stuff happen. It’s relaxing after spending my professional day wrangling huge .net solutions across multiple servers and staring at .configs until my eyes water. And just as I did back in the day, I still turn to games when I want to learn something new. They’re fun to program and they cover pretty much every aspect of a language. When I wanted to learn Silverlight I wrote GMemory, a deservedly unheralded accomplishment, but still fun to do. Recently I desired to get up to speed on JQuery, so once again I created a dumb game.

The sliding number puzzle has been around since the mid-nineteenth century. I remember my parents bought them for us to play with on long family car trips, which probably explains a lot about me. They come in various sizes, with the most standard being the fifteen-puzzle, so named because it is a 4 x 4 grid of sliding tiles with one empty spot. I didn’t know this when I started working on mine, so mine is a 35-puzzle, implemented entirely in javascript using JQuery. JQuery is brilliant, for a lot of reasons, but that’s another post. Suffice it to say that it was a lot of fun to work with, and the puzzle itself is interesting. It turns out that the mathematics of the sliding number puzzle have been studied for a long time, and it has proven to be an interesting problem for computer scientists as well, in terms of its inherent properties and the challenges of solving it.

However, before you spend much time trying to solve mine, I should mention that half the puzzles it generates cannot be solved. This is some mathematical property of the puzzle itself which was discovered by some guys named Johnson and Story back in 1879. Unfortunately you can’t tell if you are working on an unsolvable puzzle unto you get to the last number. Muwaahahahahaha. There’s a test to detect an unsolvable configuration, but I haven’t implemented it yet. I also haven’t implemented a solver. There are both search-based and pattern-based approaches to solving the sliding number puzzle, and I wanted to implement one and animate the solution, but I haven’t had the time. If you feel like trying, there’s a link to download the source files on the demo page.

Moving to a New Host

After five years running my site on Network Solutions I finally grew tired of their performance issues. It was taking 60-120 seconds to load the home page on some occasions, and inquiries to tech support just got me form replies reminding me I was on a shared platform, and advising me about optimizing my javascript and images to load from a CDN. Yes, CDNs are good. If you have tons of traffic using a CDN can move a lot of load off your server. Some day, if I have tons of traffic, I might care about CDNs. At the moment I don’t have tons of traffic, don’t aspire to having tons of traffic, and don’t think it’s taking Chrome 120 seconds to download and process the javascript in my WordPress install. But thanks for the advice, Network Solutions. I’ve moved my site to Rochen Hosting, and the pages load in about 2 seconds. Meanwhile, you might want to take a gander at the load on your MySQL servers.