Handling Fault Contracts
April 15, 2008 at 1:35 pm | In WCF | 1 CommentToday I had an issue with catching Fault Contracts thrown from my WCF service. Every FaultException type raised by the service (excluding Communication Exceptions) were caught by the client as a FaultException instead of the expected FaultException<T>.
The issue was that I defined the FaultContractAttribute(type) on the operations in the Service Implementation class instead of on the Service Contract’s (Interface class) operations.
A service should always handle/shield exceptions and throw them as either a FaultException or a FaultException<T>. These types will not cause the channel to be faulted. I recommend defining Fault Contracts to convey information about the problem to client applications, and DO NOT provide the internal exception such as service stack traces. I’ll blog a post in the future on my recommendations service exception shielding patterns.
To catch Fault Contract types on the client, make sure that each Fault Contract type you require for that service operation, ensure that the FaultContractAttribute(Type) is specified.
Service code
Error Handler
The following code is implemented in the IErrorHandler class and is based on Rory’s post on Implementing IErrorHandler . In this example, all exceptions in my WCF service are changed to FaultException<ServiceFault>.
public void ProvideFault(Exception error, MessageVersion version, ref Message fault) { // Return a 'ServiceFault' Fault Contract ServiceFault faultDetail = new ServiceFault("An error occured"); // Construct FaultException with Fault Contract and FaultReason FaultException<ServiceFault> faultException = new FaultException<ServiceFault>(faultDetail, new FaultReason("FaultReasonText")); // Construct MessageFault to return. MessageFault messageFault = faultException.CreateMessageFault(); fault = Message.CreateMessage(version, messageFault, faultException.Action); }
Service Contract
Now this is where I went wrong. I did not decorate my service contract with the FaultContractAttribute. This attribute accepts a Type parameter which should be the type of the Fault Contract.
namespace DJ.Wcf.Demo.ServiceContracts
{
[ServiceContract(Name = "DJ.Wcf.Demo.DemoService", Namespace = "DJ.Wcf.Demo")]
public interface IDemoService
{
[OperationContract]
[FaultContract(typeof(ServiceFault))]
DemoData GetDemoData(Int32 demoId);
}
}
Service Fault Contract code
Here is a defined Fault Contract used by the service and client. Being a Data Contract, it could contain a collection of error messages e.g. a collection of validation error messages for a set of fields that were incorrectly set on the service operation.
using System; using System.Runtime.Serialization; namespace Wcf.Demo.ServiceContracts { [DataContract] public class ServiceFault { public ServiceFault(String message) { Message = message; } [DataMember] public String Message { get; set; } } }
Client code
The service calling code below shows several catch statements. When the service passes back a ServiceFault, it will be caught in: catch (FaultException<ServiceFault>. All other FaultException and FaultException<T> types will be handled by: catch (FaultException fault) block.
Unhandled service exceptions will be raised and caught in: catch (CommunicationException cex) which will cause the WCF channel to fault, thus forcing the client to create a new channel.
try { using (ChannelFactory<IDemoService> channel = new ChannelFactory<IDemoService>("DemoService")) { IDemoService service = channel.CreateChannel(); channel.Open(); return service.GetPerson(42); } } catch (FaultException<ServiceFault> serviceFault) { MessageBox.Show(serviceFault.Message); } catch (FaultException fault) { MessageBox.Show("Unknown Service Fault"); } catch (TimeoutException tex) { MessageBox.Show("Service call timed out. Please retry."); } catch (CommunicationException cex) { MessageBox.Show("Unknown Communications exception occured."); }
1 Comment »
RSS feed for comments on this post. TrackBack URI
Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.
[...] 2008 Release is available on MSDNAmbrose – Creating Software is Not Like BuildingDave Jansen – Handling Fault ContractsKirk Allen Evans – Calling Web Services via AJAX – Part [...]
Pingback by Interesting Links: May 2, 2008 « Hank Wallace — May 2, 2008 #