Click here to Skip to main content
15,886,422 members
Articles / Programming Languages / C#
Tip/Trick

Exception Handling in WCF

Rate me:
Please Sign up or sign in to vote.
4.83/5 (8 votes)
30 Oct 2014CPOL4 min read 38.2K   15  
Exception handling in WCF

Introduction

In this tip, I want to demonstrate how you add exception handling to your Windows Communication Foundation (WCF) applications. Exception handling in WCF applications is slightly different from exception handling in other .NET applications. The reason for this is that a WCF service may need to serve a client that was implemented using a technology other than the .NET Framework. For this reason, a slightly different approach is required when implementing exception handling in your WCF applications.

Background

This tip will assume that the reader is familiar with implementing WCF services and clients. It is not an introductory WCF article.

A WCF service exposes certain services (or functionality) to client applications. For example, a financial WCF service may expose services relating to VAT calculations or calculating mortgage repayments. The WCF client connects to the WCF service and invokes the exposed services as required. All well and good. However, what happens in the event of an exception being thrown by the WCF service? This tip will address this question from both the client and the service side of a WCF application.

  • How should the WCF service throw an exception to a WCF client?
  • How should a WCF client catch an exception thrown by a WCF service?

As mentioned earlier, a WCF service exposes certain services (or functionality) to be consumed by client applications. These client applications may not necessarily be .NET applications. Therefore the WCF service should NOT throw a .NET exception to the client as it wouldn't be understood by the client WCF application unless it was a .NET application.

What the WCF service needs to do instead is to throw an exception that is language agnostic and that can be understood by any client written in any language, including clients that are NOT implemented using the .NET Framework. Therefore a Java client should be able to consume a WCF service and understand the exception information that is returned should the WCF service throw an exception.

So how does a WCF service throw a client agnostic exception?

Throwing WCF Service Exceptions

The FaultException is a .NET class that is designed to be used with WCF applications. They are strongly typed SOAP faults that can be thrown to any client irrespective of its underlying technology.

In the example code below, the WCF service implements a try / catch block. The catch block throws an exception of type FaultException.

C#
try
{
  //your service code goes here
}
catch (Exception ex)
{
  throw new FaultException(ex.Message);
}

The FaultException class can also be initialized using the FaultCode and FaultReason classes to add more meaningful information to your WCF service exception.

The following example code adds a FaultCode to the exception.

C#
try
{
  //your service code goes here
}
catch (Exception ex)
{
  throw new FaultException(ex.Message, new FaultCode("Add SOAP fault code here"));
}

The following example code adds both a FaultCode and a FaultReason to the exception.

C#
try
{
  //your service code goes here
}
catch (Exception ex)
{
  throw new FaultException(new FaultReason("Add SOAP fault reason here"), new FaultCode("Add SOAP fault code here"), ex.Message);
}

So it is entirely possible to return meaningful information to a WCF client using the aforementioned classes. It is also possible to specify a detail object that can contain more specific or customized information you want to return to the WCF client.

Adding Specific Information to Your WCF Exception

You can instantiate the FaultException class with an instance of a <TDetail> class. This <TDetail> class may contain more detailed information specific to the exception, or more verbose information such as information from the Exception such as the InnerException. For debugging purposes, you could add TargetSite, Source and StackTrace.

Example usage of instantiating the FaultException class with a serializable <TDetail> object.

C#
try
{
  //your service code goes here
}
catch (Exception ex)
{
  throw new FaultException<TDetail>(TDetail);
}

Here is an example of how you can implement a <TDetail> object and use it to return more detailed exception information to the WCF client.

Implement a <TDetail> Class

For the purposes of this tip, I will implement a <TDetail> class that adds Exception information which is useful for debugging / diagnostics. However, your own <TDetail> class can contain whatever information is appropriate to your application or specific to the service that is throwing it. For example, if the service is returning a Customer object, then you may want to return a <TDetail> object that exposes the Customer ID (to allow the client to display a specific error message).

Firstly, we need to define our <TDetail> class. The class is called UnexpectedServiceFault and will contain properties for exposing debugging information such as the Message, StackTrace, Source and Target. The values for these properties will be supplied from the Exception.

C#
using System.Runtime.Serialization;

namespace Common
{
    /// <summary>
    /// Generic WCF service exception. 
    /// </summary>

    [DataContract]
    public class UnexpectedServiceFault
    {
        [DataMember]
        public string ErrorMessage { get; set; }
        [DataMember]
        public string StackTrace { get; set; }
        [DataMember]
        public string Target { get; set; }
        [DataMember]
        public string Source { get; set; }
    }
}

Our service code uses the UnexpectedServiceFault class as in the example code below.

C#
try
{
  //your service code goes here
}
catch (Exception ex)
{
  throw new FaultException<UnexpectedServiceFault>(
                    new UnexpectedServiceFault { ErrorMessage = ex.Message, 
                    Source = ex.Source, StackTrace = ex.StackTrace, Target = ex.TargetSite.ToString() },
                    new FaultReason(string.Format(CultureInfo.InvariantCulture, 
                    "{0}", "Service fault exception")));
}

We have now defined how to throw meaningful exception information back to the WCF client. The next step is to catch the exceptions on the client.

Catching a WCF Service Exception on the Client

The following example code shows how our WCF client application can catch the exceptions thrown by the WCF service.

C#
try
{
  //client code goes here
}
catch (TimeoutException ex)
{
    Console.WriteLine("Service has timed out");
    Console.WriteLine(ex.Message);
}
catch (FaultException<UnexpectedServiceFault> ex)
{
    Console.WriteLine("Service error occurred: {0}", ex.Message);
    Console.WriteLine("service message: {0}", ex.Detail.ErrorMessage);
    Console.WriteLine("source: {0}", ex.Detail.Source);
    Console.WriteLine("target: {0}", ex.Detail.Target);
    Console.WriteLine("stack trace: {0}", ex.Detail.StackTrace);
}
catch (FaultException ex)
{
    Console.WriteLine("Service error occurred: {0}", ex.Message);
}

catch (CommunicationException ex)
{
    Console.WriteLine("Communications error occurred: {0}", ex.Message);
}
catch (Exception ex)
{
    Console.WriteLine("Error has occurred");
    Console.WriteLine(ex.Message);
}

The WCF client code checks for both a FaultException<UnexpectedServiceFault> and FaultException exceptions (in that order). The WCF service may therefore throw general exceptions as well as more specific exceptions, and both will be caught and handled by the WCF client.

Summary

I use this technique in all my WCF service applications. Once you have defined your <TDetail> classes, you can add as much information to your exceptions as necessary, and handle them on the client in any manner that is appropriate. Feel free to leave a comment if you would like me to further elaborate on anything within this tip.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Gold-Vision CRM
United Kingdom United Kingdom
I am a professional software engineer and technical architect with over twenty years commercial development experience with a strong focus on the design and development of web and mobile applications.

I have experience of architecting scalable, distributed, high volume web applications that are accessible from multiple devices due to their responsive web design, including architecting enterprise service-oriented solutions. I have also developed enterprise mobile applications using Xamarin and Telerik Platform.

I have extensive experience using .NET, ASP.NET, Windows and Web Services, WCF, SQL Server, LINQ and other Microsoft technologies. I am also familiar with HTML, Bootstrap, Javascript (inc. JQuery and Node.js), CSS, XML, JSON, Apache Cordova, KendoUI and many other web and mobile related technologies.

I am enthusiastic about Continuous Integration, Continuous Delivery and Application Life-cycle Management having configured such environments using CruiseControl.NET, TeamCity and Team Foundation Services. I enjoy working in Agile and Test Driven Development (TDD) environments.

Outside of work I have two beautiful daughters. I am also an avid cyclist who enjoys reading, listening to music and travelling.

Comments and Discussions

 
-- There are no messages in this forum --