Handling Exceptions in WCF Applications
In this article I will explain the use of structured exception handling using try catch blocks. Since service oriented applications are called by any clients irrespective of the technology, we should handle exceptions in a different way. Since it is not technology specific, we need some generic exception methodology in this case.
WCF unified programming model helps to build secure, reliable and interoperable applications.Since it is not technology specific, we need some generic exception methodology in this case.
In WCF, we can handle exceptions 2 ways:
a) By using .net Exception objects
b) By using SOAP fault messages
Since SOAP faults are expressed in XML format, it is highly interoperable and any clients can easily understand it. There are 2 types of SOAP defaults: declared and undeclared. For declared SOAP faults we must specify [FaultContractAttribute] attribute in the operations where in case of undeclared SOAP faults are not specified in the contract for the operation.
It is always a good practice to declare faults using [FaultContractAttribute] attribute and provide only minimum information in faults in order to minimize the information disclosure to the client. In .Net, System.ServiceModel namespace provides generic Fault Exception
We can send service exception to the client in 3 different ways.
1)Throwing exception using Exception Class
Step 1: Create sample Service with some operation and throw some general exception.
//Service interface
[ServiceContract()]
public interface IMathService
{
[OperationContract()]
int AddNum(int num1, int num2);
}
//Service implementation
public class MathService : IMathService
{
public int AddNum(int num1, int num2)
{
//Do something
throw new Exception("Error while adding number");
}
}
Step 2: Write client side code which will consume the service.
try
{
MathServiceProxy.MathServiceProxy proxy
= new MathServiceProxy.MathServiceProxy ();
Console.WriteLine("Sum of two numbers... 5+5 =" + proxy.AddNum(5, 5));
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
}
Here even though I have written to throw some exception in the service, the client will receive following message from WCF.
"The server was unable to process the request due to an internal error. For more information about the error, either turns on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs." This means exceptions are not handled properly.
2)Throwing exception using FaultException class
Here FaultException
//Service implementation
public class MathService : IMathService
{
public int AddNum(int num1, int num2)
{
//Do something
throw new FaultException("Error while adding number");
}
}
Now if any exception happens in the service, the client will receive following message from the service.
"Error while adding number".
3)Throwing with strongly typed fault.
We can also create our own custom type and send the error information to the client using FaultContract attribute. In order to create custom exception we need to follow the below mentioned steps.
i)Define the exception class using the DataContract attribute and specify the fields you want to return in the exception with DataMember attribute.
[DataContract()]
public class CustomServiceException
{
[DataMember()]
public string ExceptionMessage;
[DataMember()]
public string InnerException;
[DataMember()]
public string StackTraceInfo;
}
ii)Define the service operation with the FaultContract attribute and specify the type name.
[ServiceContract()]
public interface IMathService
{
[OperationContract()]
[FaultContract(typeof(CustomServiceException))]
int AddNum(int num1, int num2);
}
iii)Raise the exception from the service.
public int AddNum(int num1, int num2)
{
//Do something
CustomServiceException ex = new CustomServiceException();
ex.ExceptionMessage = "Error while adding 2 numbers.";
ex.InnerException = "Inner exception message from serice";
ex.StackTraceInfo = "Stack Trace message from service.";
throw new FaultException(ex,"Testing") ;
}
On the client side, we can capture the service exception if any as follows.
try
{
MathServiceProxy. MathServiceProxy proxy
= new MathServiceProxy. MathServiceProxy ();
Console.WriteLine("Sum of two numbers... 5+5 =" + proxy.Add(5, 5));
Console.ReadLine();
}
catch (FaultException
{
//Process the Exception
}
Its nice article. Thanks for posting.