I have a set of SOAP webservices that are wrapping exceptions using IErrorHandler, specifically:
public sealed class ErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
// don't wrap existing fault exceptions
if ((error is FaultException)) return;
// our basic service fault
var businessFault = new BusinessFault { FaultMessage = error.Message, FaultReference = "Internal" };
// Resource based faultReason
var faultReason = new FaultReason(Properties.Resources.BusinessFaultReason);
var faultcode = FaultCodeFactory.CreateVersionAwareSenderFaultCode(InternalFaultCodes.BusinessFailure.ToString(), Service.Namespace);
var faultException = new FaultException<BusinessFault>(
businessFault,
faultReason,
faultcode);
// Create message fault
var messageFault = faultException.CreateMessageFault();
// Create message using Message Factory method
fault = Message.CreateMessage(version, messageFault, faultException.Action);
}
}
I have now added extra endpoints for Json and Pox which work fine, unless an exception occurs. In the case of the Json endpoint the FaultException is returned as XML.
I am aware from other SO posts that in the case of REST I would be better throwing a WebHttpException:
throw new WebFaultException<BusinessFault>(detail, HttpStatusCode.BadRequest);
Or overriding the response message properties in ProvideFault, thus:
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
var rmp = new HttpResponseMessageProperty
{
StatusCode = System.Net.HttpStatusCode.BadRequest,
StatusDescription = "See fault object for more information."
};
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
However, MSDN has some interesting remarks about WebHttpException namely:
When using a WCF REST endpoint (WebHttpBinding and WebHttpBehavior or WebScriptEnablingBehavior) the HTTP status code on the response is set accordingly. However, WebFaultException can be used with non-REST endpoints and behaves like a regular FaultException.
When using a WCF REST endpoint, the response format of the serialized fault is determined in the same way as a non-fault response. For more information about WCF REST formatting, see WCF REST Formatting.
It would suggest therefore that I need to convert my current ProvideFault method to provide a new WebHttpException (wrapping any existing Exceptions or FaultExceptions) and then SOAP would still work as well.
Would anyone like to take a stab at what that would look like (.Net4.0 btw)? I want one error handler to rule them all!
In a REST application I'm working on, I created a new class derived from
WebFaultException<T>
that attaches some additional data to caught service exceptions. Calling theCreatingMessageFault()
method on the instance of the derived class let me return my selected exception data from theProvideFault()
method of the error handler as the SOAP fault, letting WCF determine the correct message format.I am using
webHttpBinding
to bind all but some third-party services.Edit: Added code example
and
then in your service, you can throw the exception to pass fault data to your client:
I was under the impression that using
webHttpBinding
was a way to get the "all-in-one" functionality of JSON/POX/SOAP as opposed to using separate bindings for each (i.e.wsHttpBinding
,basicHttpBinding
etc.). So wouldn't you be able to just throw theWebHttpException
and then have that give you all the error details you needed regardless of the technology?