20
votes

I would like to throw custom exception like some error message as an exception from WCF web service and trying receiver this exception error message in client app on calling web service method.

how to throw custom exception from WCF web Service and receive same exception error at client side.

WCF Web Service Method:

    public bool Read()
    {
        if (IsUserValid() == false)
        {
            throw new Exception("Authorized user");
        }
    }

At Client Side

try
{
   _client.Read();
}
catch (Exception e)
{
   MessageBox.Show(e.Message);
   return;
}

Result: Always throw error message as an exception **i.e.

"System.ServiceModel.FaultException: 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 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 code is throwing exception but not returning same error message as thrown from WCF web service as an exception error

Please suggest

2
You can find answer in similar question: stackoverflow.com/questions/5165004/…Milan Raval

2 Answers

70
votes

In WCF, you should not throw standard .NET exceptions - this is contrary to the potentially interoperable nature of WCF - after all, your client could be a Java or PHP client which has no concept of .NET exceptions.

Instead, you need to throw FaultExceptions (which is the standard behavior for WCF).

If you want to convey back more information about what went wrong, look at the generic FaultException<T> types:

SERVER:

public bool Read()
{
    if (IsUserValid() == false)
    {
        throw new FaultException<InvalidUserFault>("User invalid");
    }
}

Or alternatively (as suggested by @MortenNorgaard):

public bool Read()  
{ 
    if (!IsUserValid()) 
    { 
        InvalidUserFault fault = new InvalidUserFault(); 
        FaultReason faultReason = new FaultReason("Invalid user"); 

        throw new FaultException<InvalidUserFault>(fault, faultReason); 
    }   
}

CLIENT:

try
{
   _client.Read();
}
catch (FaultException<InvalidUserFault> e)
{
    MessageBox.Show(e.Message);
    return;
}

You should declare your InvalidUserFault as WCF data contracts and define what members might travel back with that type (i.e. error code, error message etc.).

 [DataContract]
 [Serializable()]
 public class BusinessFault
 {
   ... add your fault members here
 }

And you should then decorate your service methods with the possible faults it can throw:

[FaultContract(typeof(InvalidUserFault)]
[OperationContract]
public bool Read()
.....

Of course, the "quick'n'dirty" hack is to simply define that the server returns exception details in its FaultExceptions:

<serviceBehaviors>
   <behavior name="EmployeeManager_Behavior">
      <serviceDebug includeExceptionDetailInFaults="true"/>
   </behavior>
</serviceBehaviors>

and then you can inspect the FaultException's .Detail for the actual exception that happened on the server - but again: this is more of a development-time only hack rather than a real solution.

Marc

2
votes

To get this to work you need to do two things:

  • Define the fault contract in the interface (WCF contract)
  • Throw the exception as a fault exception