Wednesday, July 20, 2011

WCF, Enterprise Library & Cruise Control

[Note: This post is based upon an old blog post that I'm migrating for reference purposes, so some of the content might be a bit out of date. Still, hopefully it might help someone sometime...]

I recently had an interesting experience with Cruise Control automated builds. The scenario was this:
  • A set of web services implemented in WCF, with the constituent parts separated out into distinct projects in the Visual Studio solution: Common, Contracts, Implementation, Host.
  • The Exception Handling Application Block (EHAB) from the Microsoft Enterprise Library 4.1 was used for its great configurable exception handling & logging and exception shielding features.
  • We had automated builds set up on a build server using Cruise Control. Anytime you checked in changes to the solution, the build server would rebuild a new version and make it available for deployment to the "official" dev, test, and production environments. [This has since been changed, because it was kind of overkill and led to about a million (overstating) builds per day]
I was working on a local dev machine, modifying the web services, running them locally, and performing my unit tests successfully. Checked in my changes and asked for the latest build to be deployed to the "dev" web server, ran the same unit tests, the unit tests ran fine until I executed a test that was intended to produce an error that needed to be handled by the EHAB configuration. Instead of the logging and custom Fault I was expecting, I got the default "shielded" Fault and exception message produced by the EHAB "An error has occurred while consuming this service. Please contact your administrator for more information. Error ID: {handlingInstanceID}".

Hmm... I double-checked that I was indeed sending in exactly the same "bad" request, that should be generating the exception I was expecting, and that the EHAB configuration should be handling it. Yes indeed.

To cut a long story of investigation and frustration short, it came down to a "clash" between the automated build in Cruise Control and my EHAB configuration.

My EHAB configuration was attempting to transform from a particular Exception type to a particular (custom) Fault Contract type using the Fault Contract Exception Handler. The EHAB configuration was referring to the Fault Contract type using the fully qualified strong name of the assembly, including the version number.

Now here's where Cruise Control was coming into the picture. The "standard" Cruise Control build script was, prior to build, performing a substitution within any AssemblyInfo files it was building, to replace the text "1.0.0.0" with the current Cruise Control build number. In my case, as this was a new solution, I hadn't changed the AssemblyInfo version numbers from their defaults of 1.0.0.0, and hence when my solution was built by Cruise Control, the assemblies ended up with the Cruise Control-generated version numbers. Of course, this led to EHAB looking for the assembly within which my Fault Contracts were located with a particular version (1.0.0.0), and the actual assembly that was deployed had a version number nothing like this.

Although I kind of objected to the rather agricultural textual "find-and-replace" in the Cruise Control build script, I wasn't in a position to be able to change it. The solution ended up being to modify my EHAB configuration to include the "short" version of the Fault Contract & Assembly name, rather than the "long" version (I'm sure there are official names for these). So, instead of something that looked like this:

XYZ.Service.Contract.ServiceOperationFault, XYZ.Service.Contract, Version=1.0.0.0, Culture=neutral, PublicKeyToken=...

I replaced it with something like this:

XYZ.Service.Contract.ServiceOperationFault, XYZ.Service.Contract

This works fine in my case because the assembly is deployed alongside everything else, in the bin folder for the web services.

No comments:

Post a Comment