Managing binary dependencies in .NET can be a complicated task. For small projects, checking the dependencies into source control tends to work just fine. So does requesting that all developers have various binaries available in their GAC. Grow much bigger, or add more projects, and managing that starts to get very difficult.
The Java world has had a solution to this problem for a long time, in the form of Maven and Ivy. Remote servers store the binaries, and the build tool automatically downloads them on demand. WebGAC adds the core of this functionality to .NET, but without requiring you to switch build tools, or maintain a separate configuration file. Dependencies are specified just the same way as normal, but if you don’t have them when building your project, WebGAC will fetch them for you automatically.
WebGAC is available at http://github.com/paulj/webgac. Browse over there for more information and installation instructions, or continue reading here for more details.
The Remote Server
A WebGAC remote server is as simple as an Apache HTTP server running the DAV extensions. The DAV extensions provide the ability to query (in a structured form) for directory lists, and to upload new files remotely.
WebGAC in MSBuild and Visual Studio
To do its thing, WebGAC requires that a custom Import of targets is added to each project. This is as simple as adding the following block:
<Import Project="$(MSBuildExtensionsPath)\WebGAC\WebGAC.targets" />
This import adds all the necessary hooks for doing remote dependency resolution using your project’s normal references. Any missing assemblies will be automatically downloaded and inserted into your build.
The WebGAC Visual Studio add-in provides mechanisms for configuring the WebGAC extension (eg, setting up remote servers), browsing the remote servers and uploading binaries to the remote servers.
The imported MSBuild targets file also includes targets that allow the assembly produced by the current project to be uploaded to a WebGAC – thus allowing for the release of binaries either from developer machines or from a continuous integration environment.
The Gory Details
This section discusses how WebGAC actually does what it does. If you’re just interested in using WebGAC, feel free to skip it.
As a standard property within the MSBuild environment for a .NET project, the AssemblySearchPaths property is defined as:
<AssemblySearchPaths> {CandidateAssemblyFiles}; $(ReferencePath); {HintPathFromItem}; {TargetFrameworkDirectory}; {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)}; {AssemblyFolders}; {GAC}; {RawFileName}; $(OutputPath) </AssemblySearchPaths>
The WebGAC targets import overrides this, by inserting a {WebGAC} target after the {GAC} element. It also overrides the ResolveAssemblyReferencesDependsOn variable (which defines the standard set of tasks to execute when preparing Assembly Resolution) to execute the target AddWebGACAssemblySearchPaths. This target will query it’s own cache (and any configured remote web servers) for the project’s references. If they are available via the WebGAC, it will download the files and insert the local cache directories into the search paths. MSBuild and Visual Studio will treat these new paths as if they came from any other standard part of the build system, and incorporate them transparently into the build. Visual Studio will even treat the assemblies as if they came from the GAC!
If WebGAC sounds like it could be useful to you on your .NET project, head over to http://github.com/paulj/webgac. There is even a pre-built installer to get you going quickly!