WCF Web Service Custom Exception Error to Client

wcf

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

Best Answer

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