Error Handling
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
This topic demonstrates how to enable the fault behavior of your WCF Service and how to handle exceptions on the client.
What are Faults?
Faults and exceptions are not the same thing. Exceptions are a .NET Framework mechanism that is used to communicate problems during the program executions. You can throw, catch, handle, and ignore exceptions so that they can be further propagated up the call stack. At some point, they should be handled or .NET will terminate the thread in which the exception is thrown. On the other hand, faults are SOAP mechanism for transferring errors from a service to a client.
Configuring Fault Behavior of your WCF Service
This section shows how to enable the fault behavior of your WCF Service and what type of information will be sent with the fault.
The FaultException Class
When your service implementation throws a FaultException, WCF takes care of serializing that back to the customer as a SOAP fault. There are two versions of the class:
- FaultException - sends untyped fault data to the client.
- FaultException<T> - a generic version, used to send typed fault data to the client. The type argument represents the detailed fault information that will be serialized to the client as part of the SOAP fault message. You can specify your own custom class as the type parameter. Client applications catching the fault exception can access the fault information by getting it from the exception object's Detail property.
The FaultContractAttribute
The FaultContractAttribute enables you to declare which faults a given service operation might issue. The attribute can be applied multiple times on a single operation; for instance, if your operation might return different types of faults.
The following example demonstrates, first, how to declare a service might issue faults, and, second how the service operation might create and throw a new FaultException.
[ServiceContract]
public interface IEntitiesModelService
{
[OperationContract]
[FaultContract( typeof( string ) )]
[FaultContract( typeof( DemoFault ) )]
CarDto GetCar( string make, string model );
}
public partial class EntitiesModelService
{
public CarDto GetCar( string make, string model )
{
if ( string.IsNullOrEmpty( make ) || ( string.IsNullOrEmpty( model ) ) )
{
throw new FaultException<string>( "Invalid Parameters." );
}
CarDto car = this.CarService.GetAll().FirstOrDefault(c => c.Make == make && c.Model == model);
if ( car == null )
{
throw new FaultException<DemoFault>( new DemoFault( string.Format( "Cannot find {0} {1}.", make, model ) ) );
}
return car;
}
}
[DataContract]
public class DemoFault
{
public DemoFault( string errorText )
{
this.ErrorText = errorText;
}
[DataMember]
public string ErrorText
{
get;
set;
}
}
<ServiceContract>
Public Interface IEntitiesModelService
<OperationContract, FaultContract(GetType(String)), FaultContract(GetType(DemoFault))>
Function GetCar(ByVal make As String, ByVal model As String) As CarDto
End Interface
Partial Public Class EntitiesModelService
Public Function GetCar(ByVal make As String, ByVal model As String) As CarDto _
Implements IEntitiesModelService.GetCar
If String.IsNullOrEmpty(make) OrElse (String.IsNullOrEmpty(model)) Then
Throw New FaultException(Of String)("Invalid Parameters.")
End If
Dim car As CarDto = Me.CarService.GetAll(). _
FirstOrDefault(Function(c) c.Make = make AndAlso c.Model = model)
If car Is Nothing Then
Throw New FaultException(Of DemoFault)(New _
DemoFault(String.Format("Cannot find {0} {1}.", make, model)))
End If
Return car
End Function
End Class
<DataContract>
Public Class DemoFault
Public Sub New(ByVal errorText As String)
Me.ErrorText = errorText
End Sub
<DataMember>
Public Property ErrorText() As String
End Class
Handling Exceptions in the Client
On the client side, a FaultException is caught just like any other exception, as it's shown here:
EntitiesModelServiceClient serviceClient = new EntitiesModelServiceClient();
try
{
CarDto car = serviceClient.GetCar( "Opel", "Astra" );
Console.WriteLine( car.CarID.ToString() );
}
catch ( FaultException<string> exception )
{
Console.WriteLine( exception.Detail );
}
catch ( FaultException<DemoFault> exception )
{
Console.WriteLine( exception.Detail.ErrorText );
}
Dim serviceClient As New EntitiesModelServiceClient()
Try
Dim car As CarDto = serviceClient.GetCar("Opel", "Astra")
Console.WriteLine(car.CarID.ToString())
Catch exception As FaultException(Of String)
Console.WriteLine(exception.Detail)
Catch exception As FaultException(Of DemoFault)
Console.WriteLine(exception.Detail.ErrorText)
End Try
The exceptions defined in the catch statements are the generic version of the FaultException class. The Detail property exposes the instance of the fault type returned by the service, e.g. string or DemoFault.