Saturday, September 7, 2013

Exception Handling in WCF Service

WCF service sends below message to client whenever any error occured in WCF

The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the <serviceDebug> 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 is because by default, the service does not send any information explaining what happened. WCF does not reveal details about what the service does internally. This makes the service more secure.


However, it would be more convenient to see additional details regarding failures. In the Solution Explorer, double-click Web.config. Scroll to the bottom of the file and make the following change in bold:
<serviceBehaviors>
  <behavior name="ServiceBehavior">
    <serviceMetadata httpGetEnabled="true"/>
    <serviceDebug includeExceptionDetailInFaults="true"/>
  </behavior>
</serviceBehaviors>
Now WCF runtime will send error message to client readable format. 
But we can not throw wcf exception by using the below simple way as we usually do in C# code...

catch (Exception ex)
       {
          throw new ex.Message;
       }

Below there are ways to handling exceptions in WCF...

1- Use the FaultException Class to Handle Exceptions...

Use below code in wcf service class method to throw exception to client...

catch (Exception ex)
     {          
        throw new FaultException ex.Message;
     }

and then use below lines to capture exception at client...



catch (FaultException faultEx)
      {
         Console.WriteLine(faultEx.ToString());

      }


2- Throw Strongly Typed SOAP Faults to Provide More Detail to Clients



Currently, the WCF service throws one type of exception: a FaultException. Essentially, the service throws a generic fault, although the fault code enables the client to distinguish the reason for the fault. You could throw faults that are more specific. For example, you could throw a SqlException object when the service can’t connect to or read from the database.
This, however, violates one of the principles of service-orientation. In a service-orientated application, services and client communicate by passing messages. Neither is aware of how the other is constructed. Throwing a SqlException object from a WCF service assumes clients know about .NET exception types.
A more practical problem is that clients would need to know how to handle a SqlException object. While a .NET client certainly could, a Java application or VBA code in an Excel workbook would not.
Rather than throw .NET exceptions, you can throw strongly typed SOAP faults. To do that, you first create classes that represent faults. The properties of these classes can store detailed information about the faults. You then add these classes to the service’s data contract. Finally, you use the FaultContractAttribute to identify which operations can throw which SOAP fault.
Example: Create a class to display the fault.
[DataContract()]
public class CustomException
{
  [DataMember()]
  public string Title;

 [DataMember()]
 public string ExceptionMessage;

 [DataMember()]
 public string InnerException;

[DataMember()]
public string StackTrace;
}

Use this class in Fault Contract attribute...

    [OperationContract]
    [FaultContract(typeof(CustomException))]
    List<Product>GetProducts();

now put below code inside catch block of your service method in Service.cs file...

catch (Exception ex)
  {
    CustomException ObjEx = new CustomException();
    ObjEx.Title = "WCF Service Error";
    ObjEx.ExceptionMessage = ex.Message;
    ObjEx.InnerException = ex.InnerException.ToString();
    ObjEx.StackTrace = ex.StackTrace;
    throw new FaultException<CustomException>(ObjEx, "Reason :" + ex.ToString())
   }

above code will throw exception to client.  


To trap the strongly-typed faults, make the following changes in the client code...


catch (FaultException<CustomException> FaultEx)
  {
   
   Console.WriteLine("WCF Error Message: "+  FaultEx.Details.ExceptionMessage
   + "WCF Error InnerException: "+ FaultEx.Details.InnerException
   + "WCF Error StackTrace: "+  FaultEx.Details.StackTrace);
   
 }


---


References:
http://msdn.microsoft.com/en-us/library/ee942778.aspx

No comments:

Post a Comment