MSBuild: Dependencies (3 of 7)
November 29th, 2006I often use a build script to prepare a project the first time it is pulled out of source control. Normally the Solution and Project files handle all of the dirty details necessary to build the project but with ASP.NET 2.0 some trouble was introduced. The new ASP.NET 2.0 Website model has a great deal of flexibility, but it gained that flexibility by eliminating the project file which changed how dependencies are managed.
When a dependency for an assembly is added to a website it simply places that assembly into the bin folder for the website. It will then place a file using the name of that assembly with .refresh appended to the end. That file points to the location of the source assembly. On the next build, that source file is checked and copied into the bin folder if it has changed. It seems all well and good, but I have had considerable trouble with this system.
First of all, these files end up being copied into source control. And whenever someone is working on the website and then runs a build with an update to one of those assemblies, the updated assemblies are checked out (potentially exclusively) to that developer which causes problems for the rest of the team. To prevent such problems, I simply do not source control anything in the bin folder. In fact, I set my source control system to completely ignore the bin folder.
Instead, I have MSBuild create that directory and copy in files I manage outside of the website which will not cause exclusive locks to slow down the development team.
My first attempt at scratching this itch was to set up a project as shown in the image to the right. I would create a folder called SharedAssemblies next to the Website directory and place all of the dependencies in the SharedAssemblies folder. When the developer pulls the Solution from source control they could manually create the bin folder for the Website and copy over the assemblies, or they could run the following build script.
If this procedure was used across all projects maintained by the development team the developers would know to run the build immediately after building it from source control. The above script creates the folder Website\bin and then copies all of the files in the ShareAssemblies folder into the bin folder. (Alongside the build script I have a file called PreBuild.cmd which calls MSBuild and specifies the PreBuild target so the developer can just double-click the script.) I used this approach for a while and then came up with a better approach.
With my new approach I take full advantage of the fact that I still have a Solution file which manages multiple projects. So I start with the sample project above and then add another project called ClassLibrary which does still have a project file including a dependency manifest. I add all of the assembly references necessary for the Website to the ClassLibrary and then add a Project dependency for the Website to the ClassLibrary. Since the Solution records that relationship and the ClassLibrary holds the dependency manifest, the Solution will allow the Website to build straight from source control. When the Website is built the chain of dependencies will cause all of the ClassLibrary dependencies to be copied into the Website\bin folder even if the ClassLibrary defines no classes itself. I have found this to be a reliable way to indirectly manage dependencies for an ASP.NET 2.0 website.
More Information:
Next in this series, configurations.

February 21st, 2008 at 11:42 am
Hi
Thank you for the highly valuable information you have published here. Your style is clear, helpful and enjoyable.
You should write a book!
Best regards
Warren van Niekerk