I have a WCF 4 Rest service that is to be consumed by a java client and also an c# mvc3 client. The response content needs to be returned as json.
I want to be able to return any exception/faults back to clients in a consistent way. I read that WebFaultException should be used and indeed it works fine.
However, I do not want to pollute my application logic project with WebFaultExceptions as it may be used by a non web project.
I therefore looked at implementing IErrorHandler in the WCF Rest service to catch ANY exceptions and then for specific ones i.e. ValidationException, return the exception as a fault wrapped in a WebFaultException. However this doesn't seem to work and I get the following Http 504 response when called form fiddler
[Fiddler] ReadResponse() failed: The server did not return a response for this request.
I've reduced the code to its bare bones to show the essence of what I'm doing.
public void ProvideFault(Exception error,
MessageVersion version,
ref Message fault)
{
var ex = new WebFaultException<Exception>(
new Exception("you can't do that"),
HttpStatusCode.Unauthorized);
var xmf = ex.CreateMessageFault();
fault = Message.CreateMessage(version,
null,
xmf,
new DataContractJsonSerializer(xmf.GetType()));
}
What am I doing wrong?
Here is a sample code from Carlos's blog. It helps me in the past.
public class ValidationAwareErrorHandler : IErrorHandler
{
IErrorHandler originalErrorHandler;
public ValidationAwareErrorHandler(IErrorHandler originalErrorHandler)
{
this.originalErrorHandler = originalErrorHandler;
}
public bool HandleError(Exception error)
{
return error is ValidationException || this.originalErrorHandler.HandleError(error);
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
ValidationException validationException = error as ValidationException;
if (validationException != null)
{
fault = Message.CreateMessage(version, null, new ValidationErrorBodyWriter(validationException));
HttpResponseMessageProperty prop = new HttpResponseMessageProperty();
prop.StatusCode = HttpStatusCode.BadRequest;
prop.Headers[HttpResponseHeader.ContentType] = "application/json; charset=utf-8";
fault.Properties.Add(HttpResponseMessageProperty.Name, prop);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));
}
else
{
this.originalErrorHandler.ProvideFault(error, version, ref fault);
}
}
class ValidationErrorBodyWriter : BodyWriter
{
private ValidationException validationException;
Encoding utf8Encoding = new UTF8Encoding(false);
public ValidationErrorBodyWriter(ValidationException validationException)
: base(true)
{
this.validationException = validationException;
}
protected override void OnWriteBodyContents(XmlDictionaryWriter writer)
{
writer.WriteStartElement("root");
writer.WriteAttributeString("type", "object");
writer.WriteStartElement("ErrorMessage");
writer.WriteAttributeString("type", "string");
writer.WriteString(this.validationException.ValidationResult.ErrorMessage);
writer.WriteEndElement();
writer.WriteStartElement("MemberNames");
writer.WriteAttributeString("type", "array");
foreach (var member in this.validationException.ValidationResult.MemberNames)
{
writer.WriteStartElement("item");
writer.WriteAttributeString("type", "string");
writer.WriteString(member);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}