Monday, September 24, 2007

Exception Handling in WCF

I have recently had the pleasure (yes, it really is a pleasure!) to work a bit closer with the new .NET technologies such as Windows Communications Foundation (WCF). One of the things that I've found myself struggling with is some of the more esoteric aspects of precedence in exception handling. (Yeah, I know, this is basic stuff, but I was surprised at how I got caught with this and figure maybe there's one or two more out there that can benefit from my bumbling)

Consider the following code snippet (from MSDN):

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.WCF.Documentation;

public class Client
{
public static void Main()
{
// Picks up configuration from the configuration file.
SampleServiceClient wcfClient = new SampleServiceClient();
try
{
// Making calls.
Console.WriteLine("Enter the greeting to send: ");
string greeting = Console.ReadLine();
Console.WriteLine("The service responded: " + wcfClient.SampleMethod(greeting));
Console.WriteLine("Press ENTER to exit:");
Console.ReadLine();
}
catch (TimeoutException timeProblem)
{
Console.WriteLine("The service operation timed out. " + timeProblem.Message);
wcfClient.Abort();
Console.ReadLine();
}
// Catch the contractually specified SOAP fault raised here as an exception.
catch (FaultException<GreetingFault> greetingFault)
{
Console.WriteLine(greetingFault.Detail.Message);
Console.Read();
wcfClient.Abort();
}
// Catch unrecognized faults. This handler receives exceptions thrown by WCF
// services when ServiceDebugBehavior.IncludeExceptionDetailInFaults
// is set to true.
catch (FaultException faultEx)
{
Console.WriteLine("An unknown exception was received. "
+ faultEx.Message
+ faultEx.StackTrace
);
Console.Read();
wcfClient.Abort();
}
// Standard communication fault handler.
catch (CommunicationException commProblem)
{
Console.WriteLine("There was a communication problem. " + commProblem.Message + commProblem.StackTrace);
Console.Read();
wcfClient.Abort();
}
}
}

Notice that the generic CommunicationException is handled as the last item in the catch block. The reason for this is that FaultException is actually derived from CommunicationException. This causes any FaultExceptions to be caught by the CommunicationException handler...

What this means practically is that you must take care and order your exception handlers properly when dealing with these types of Exceptions. Generally speaking, when writing WCF-based code, you'll want to structure your exception handlers similar to the sample above.

No comments: