Search code examples
c#jsonwcfrestierrorhandler

wcf rest ierrorhandler webfaultexception


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?


Solution

  • 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();
            }
        }
    }