Joel
Joel

Reputation: 8988

REST WCF Service with IErrorHandler catches SerializationExceptions

I have a REST WCF service with a custom IErrorHandler, so that I can catch all uncaught exceptions in my service and return a custom error message, a proper Http status code (500) and log the error.

The problem is that the IErrorHandler will catch exceptions not originating from my code, so if I for example make a POST to the service with invalid JSON data, I will get a SerializationException. That exception would have been transformed into a WebFaultException with status code BadRequest 400, if it weren't for my IErrorHandler, where I will handle it just like all other uncaught exceptions.

Is there a way of dealing with these situations or should I just catch SerializationExceptions in my IErrorHandler and set BadRequest there? What other exceptions might orginate from the WCF stack without coming from my code?

Update: Added my implementation of IErrorHandler.ProvideFault

 public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        Guid loggingId = Guid.NewGuid();
        error.Data["ExceptionLoggingId"] = loggingId;

        if (error is SecurityTokenException)
        {
            fault = Message.CreateMessage(version, string.Empty, String.Format("{0}. The error identifier is {1}", error.Message, loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.Unauthorized);
        }
        else
        {
            if (error is SerializationException)
            {
                // TODO: What if the SerializationException originates from within the service?
                // SerializationException due to malformed JSON
                return;
            }

            fault = Message.CreateMessage(version, string.Empty, String.Format("An unknown error has occurred. The error identifier is {0}", loggingId), new DataContractJsonSerializer(typeof(string)));
            fault.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Json));

            webOperationContextWrapper.SetOutgoingResponseStatusCode(HttpStatusCode.InternalServerError);
        }
}

Upvotes: 2

Views: 2242

Answers (2)

DomenicDatti
DomenicDatti

Reputation: 662

I think @RichardBlewett has it right. You're going to want to create a custom exception class and throw that, check for that type in the error handler and then let the standard Serialization exception flow through normally. That seems like the best design pattern to me.

Then you get a type safe exception that if you remove or change, the error handler code won't compile or will get refactored with the type if you do it via VS. Testing the namespace like that would probably be less than advisable (though very clever), since it's not directly tied to any type at compile time. If you change namespaces around, you would run into a problem that's difficult to track down.

Upvotes: 0

Sam
Sam

Reputation: 2201

I ran into a similar issue.

My Solution has been to use the namespace to determine the origin of the exception.

if (!error.StackTrace.TrimStart().StartsWith("at " + this.GetType().Namespace.Split('.')[0]))
    return;

This works in my current project. But depending on your project, it may not...

Upvotes: 1

Related Questions