Saturday, June 12, 2010

Using FaultContract in WCF to handle exceptions

FaultContract is the word which came with WCF.As its name states it is for handling the faults.But how can we handle the fault? In this post I am just going to describe about implementing the FaultContract and its handling at client side.

What is FaultContract

It is just an attribute which is used to decorate the service method which is already marked as OperationContract.This tells that the method may throw the Fault using the specified generic class.Oh.What is this generic class? Just look at the code.

<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
<FaultContract(GetType(MyException))> _
Function GetChar(ByVal data As String, ByVal position As Integer) As Char


MyException is the generic class which I mentioned.Its just a class used to transmit the custom details about the fault to the client.

<DataContract()> _
Public Class MyException
Dim m_Message As String = String.Empty
<DataMember()> _
Public Property ExMessage() As String
Get
Return m_Message
End Get
Set(ByVal value As String)
m_Message = value
End Set
End Property

Public Sub New()
End Sub
Public Sub New(ByVal message As String)
MyBase.New()
m_Message = message
End Sub
End Class


Dont forget to mark this class as DataContract.This class is normally known as ExceptionDetail or detailType in other sites and tutorials.
Invoking the Fault

In your service implementation you can have the try catch blocks and from the catch you can throw the FaultException.It will reach up to client and client can handle that.Also you can throw the Fault from  anywhere in your code.

Public Function GetChar(ByVal data As String, ByVal position As Integer) As Char Implements IMyService.GetChar
Try
Return data(position)
Catch aEx As IndexOutOfRangeException
Dim a As MyException = New MyException(aEx.Message)
Throw New FaultException(Of MyException)(a)
Catch aEx As Exception
Dim a As MyException = New MyException(aEx.Message)
Throw New FaultException(Of MyException)(a)
End Try
End Function


Even if you didn’t handle the exception it will reach to client if your web.config is proper.ie ServiceBehaviour is as follows

<behavior name="WcfService2.Service1Behavior" returnUnknownExceptionsAsFaults="True">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>


Server side
Lets see what are all the things we need to do at the server side.

  1. Create the  class to transmit the exception details.


  2. Mark the service methods with FaultContract attribute by passing the detail class.


  3. Change your web.config to set includeExceptionDetails to true.


  4. Throw the FaultException from your service implementation from where ever required.


Client side

  1. Add the service reference.

  2. Wrap the service call with try catch and handle the FaultException.

    Private Sub GetChar(ByVal no1 As String, ByVal no2 As Double)
    Try
    Dim service As New ServiceReference1.MyServiceClient
    MessageBox.Show(service.GetChar(no1, no2))
    Catch ex As FaultException(Of FaultContractTest.Core.MyException)
    MessageBox.Show(ex.Detail.ExMessage)
    Catch ex As FaultException
    MessageBox.Show(ex.Message)
    Catch ex As Exception
    MessageBox.Show(ex.Message)
    End Try
    End Sub




You can download a sample from my sky drive which implements the above.