Andre's Blog

Personal blog of Andre Perusse

Team Foundation Build and Web Deployment Projects

Last week I decided it was time to start generating regular builds of the web application my team is developing. We're using Team Foundation Server as our source control system, so it was a natural choice to use Team Foundation Build (TFB) to generate the compiled application. Unfortunately for me, TFB is a version 1 Microsoft product which means, well, there are a few things that don't work quite right or as well as you might hope.

Installing TFB was easy, though I would have thought it would have been automatically installed with the Team Foundation Server (TFS) install. However, your build server might not be your TFS server, so this does make some kind of sense. Configuring a new Build Type was also easy, though this brings up a whole new issue. A Build Type consists of various parameters on the configuration of the compiled code you want. However, there is very little guidance I could find on the rationale for selecting various configuration options. As it turns out, for building a web application, you must be very precise with this configuration or nothing will work. The "Active solution configuration" isn't so important, but the "Active solution platform" must be "Mixed Platforms" or you won't get any satisfaction.

Before I continue, there are a few things you must know about the solution I was attempting to build. The solution contains about six projects, and the web site itself has several references to other assemblies. Both of these conditions weigh heavily on how successful you'll be using TFB to build the solution. First, the number or projects, or more precisely, the type of projects included in the solution. The current release of TFB can't deal with either Database Projects (regular ones, not the new stuff in Data Dude) or with Reporting Services Projects. With Database Projects, you'll only get a warning during the build, but with Reporting Services Projects you'll get an error and the build will be marked as "Failed." Now, using the Configuration Manager in Visual Studio, you can indicate which projects are supposed to get built when the solution is built (meaning you can exclude certain projects). This works in Visual Studio, but TFB ignores such settings and tries to build everything in the solution anyway. The only way to fix this is to remove the offending projects from your solution. Very irritating.

Now comes the really fun part. We use a Web Deployment Project (WDP) to compile the web application into a folder that can be simply "xcopy"'d to a deployment folder. On our local developer workstations this works great. On TFB, you're in for a world of hurt. First off, TFB has no idea what a WDP is, so you'll get all kinds of build errors when it sees this and tries to build it. You have to either install the WDP add-in on your build server, or at least copy the relevant files to the proper location on the build server. Once that's done, TFB can perform a build on WDPs, but this will generally fail until you take some extra steps.

First, your web application's external file assembly references have to be set up so that TFB can see them. The best way to do this is to add a "Solution Folder" to your existing solution, and place all assemblies that your web application references in here. Then make sure to re-reference these assemblies in your web project so that it knows where to find the new location. If you do this, then TFB will find all the referenced assemblies because they become part of the solution and are referenced by relative path.

Next (and this is the real tricky part), you have to tell all the other projects in your solution upon which the web site depends to copy their compiled assemblies into the web project's bin folder. In Visual Studio, you would do this simply by making a project reference from the web site to another project but the combination of TFB and WDP has no idea how to deal with this. When your WDP is compiled, it will complain that it can't find the appropriate assembly references (errors such as "Type 'MyClass' is not defined") and the build will fail. To get around this, you have to add a post-build event to all projects in the solution upon which the web site is dependent. In my solution, for example, I have two class libraries that the web site depends on - a Business Layer library and a Data Access Library. In both of these projects, I have to specify a post build event command that will copy the compiled assemblies to the bin folder of the web project.

xcopy /Y /S /F "$(TargetPath)" "$(SolutionDir)WebProjectRoot\bin"

(by the way, the quotation marks are very important if your paths have spaces in them, as I learned when xcopy gave me an "exited with code 4" message - very helpful)

Once you have done this and if the planets are aligned just so, your web solution will finally have a successful build in TFB. Of course, the next question is "what do I do once the thing finally builds?" For me, I wanted to be able to navigate to the build server in a web browser so I could see what the latest build looks like (we also use Automaton to perform continuous integration - ironically, Automaton was the easiest component of this entire mess to get set up properly). What I ended up doing was simply creating a virtual directory to the build location for the WDP on the build server. It's always in the same location, so on every build the directory is updated with the latest bits. It works, and now everyone is happy (okay, maybe only I'm happy because it took me four bloody days to get this far and it's nice to finally have a sense of accomplishment).

Here are some references I found helpful in between beating my head on my desk trying to get this all to work:

Web Deployment projects in a Team Build (Martijn Beenes)

Resolving file references in team build (Manish Agarwal)

Team Build, Web Applications, Lemon Juice and Paper Cuts (Rob Conery)

Also, thanks to Luis Fraile and Swaha Miller on MSDN Forums for helping me with this problem.

Comments (5) -

  • Rob

    11/8/2006 5:57:48 AM |

    So it doesn't seem like the build system is ready for "prime time" in VTS. Oh well back to using the monkey!

  • Luis Fraile

    11/11/2006 1:26:28 AM |

    You are welcome Andre, and about what Rob said, I think it is ready for prime time, but we have to remember the state TFS is at this moment: v1, and it really have a lot of nice features for v1, new ones are also coming with SP1, and the next year we will have v2, so I don't think is as bad as "not ready for prime time", it would be nice this kind of things didn't happen, in this kindf of products of course, but if the product is not build incrementally, and so on, it will never come to light such a big product.

    Maybe we can argue about licensing prices, but that's another question :o)

  • Andre Perusse

    11/12/2006 8:24:34 AM |

    Yeah, the support for web projects seems a little lacking. Though, as Luis says, they have to start somewhere and if you're building WinForms stuff, I imagine it would work just fine. There's a lot of added value with the integration of the build system with the TFS SharePoint site, and all the built-in reporting. I would definitely recommend spending some time with it - it has quite a bit of value right now and promises to become even more powerful in future releases.

  • Andrew

    9/27/2007 9:35:27 AM |

    Thanks Andre, very helpful post.

    I'm having an issue where Team Build doesn't even *attempt* to build my web deployment project. It is definitely set up to do so in the configuration manager and it builds when I build the solution.
    Any idea what could be wrong?

    I'm actually only using a web deployment project in order to do exactly what you have done above - the built website is copied to our development web server for UAT. I would actually prefer to have that task defined within the Team Build itself, and remove the web deployment project. Is this possible?

  • Andre Perusse

    9/28/2007 11:07:58 PM |

    Hi Andrew,

    Unfortunately, I have since moved to a different company, and while we use TFS, we don't use Team Build so I haven't looked into this any further. But I wish you the best of luck with your problem.