Let's say I have the following request object:
[DataContract]
public class MyContract {
[DataMember]
public Guid Token { get; set; }
}
And a WCF service definition as follows:
[ServiceContract]
public interface IMyService {
[OperationContract]
bool Validate(MyContract request);
}
If I send the following to the operation, I get the desired response:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:esi="http://mynamespace.com/" xmlns:con="http://mynamespace.com">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<esi:Validate>
<esi:Token>9192ef6a-819f-4a8a-8fde-4125999e33dc</esi:Token>
</esi:Validate>
</soapenv:Body>
</soapenv:Envelope>
If I send an invalid Guid (this occurs with any type), I get the following response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
<faultstring xml:lang="en-GB">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 SDK documentation and inspect the server trace logs.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
Which is all well and good, but not really enough information for my consumers, considering my service knows exactly what's wrong with the data.
I can expose the full exception with the <serviceDebug includeExceptionDetailInFaults="true"/>
web config setting, but that's TOO MUCH information for my consumers! I would rather customise the error at the code level, but I'm not sure how I can attach to the deserializer? I know how to deal with custom SOAP faults and FaultContracts, but this seems to be at a lower level - I need to intercept the incoming message before it hits the CLR methods, somehow? Is there a way to do this that I'm not aware of?
The deserializer is on the IDispatchMessageFormatter
You can hook this up via an OperationBehavior:
Hook up the OperationBehavior to your service operations via an attribute.
If you need to use configuration, attach them via a ServiceBehavior or EndpointBehavior
You can catch errors and handle them by implementing the IErrorHandler.
Try attaching this to a service behavior: