I’ve seen countless WCF self-hosting code samples in books and on forums (including MSDN which really should know better) where a
using block surrounds construction of a new
System.ServiceModel.ServiceHost instance. However this is not good practice as I’ll explain. I’m sorry to say that even in Michele Leroux Bustamante’s excellent book Learning WCF, her hosting examples contain
using blocks which caused me several wasted hours trying to figure out what was going wrong, which is why I’m sharing this with you now.
To understand the problem you need to understand the relationship between the C#
using statement and the
IDisposable interface. Classes that inherit
IDisposable must implement a single
Dispose method and when you instantiate a class that implements
IDisposable in a
using statement, the
Dispose method is called automatically before the object goes out of scope. This is a simple pattern which guarantees clean-up. Great, so why is this a problem with
System.ServiceModel.ServiceHost? Well to see the problem you need to expand the
using statement block out into its compiled syntax.
The following example shows the code you would put in the Main method of a console app to host a WCF service library, before compilation:
And this is what the above code actually looks like after compilation (notice the extra braces to define object scope):
Because exception handling is in place, at first glance this doesn’t seem like a problem. But any exceptions thrown in response to the call to
ServiceHost.Open (e.g. incorrect service configuration) will automatically cause code in the finally block to be executed. And calling
ServiceHost.Dispose after a channel fault will raise a second, rather ambiguous
CommunicationObjectFaultedException and because there is no inner exception, you lose the original exception information and have no idea what actually caused the channel to fault in the first place.
Here is the rather unhelpful exception message I kept seeing in my console window when I first hit this problem:
So how can you prevent this? Well the solution is to avoid a
using statement altogether and implement your own
try-finally block, taking more care about how you call
So now if your WCF service is incorrectly configured, you’ll see a more meaningful exception message and be able to diagnose the problem without wasting time.