Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WCF REST Services - Generic exception handling

Tags:

rest

.net

wcf

I have a lot of legacy code that is now a backend for a WCF REST service - it used to be a usual WCF service backend before, if that matters. I want to implement a mechanism that would catch any exception in any method and analyze it. If it turns out to be a known error, it will be processed and turned into a friendly-looking fault.

I know that I can throw FaultException or WebProtocolException instead of 'usual' exceptions, but there are lots of places where exceptions are thrown all over the code, and looking for all of them is quite a painful option.

I tried to add an endpoint behavior extension that creates a new behavior which overrides standard WebHttpBehavior.AddServerErrorHandlers method and adds my error handlers (IErrorHandler implementations) to the endpoint dispatcher error handlers collection. Inside the error handlers I analyze the exception and create (or do not create) a desired fault basing on this exception.

I expected this mechanism to return custom data for any known exception, but I was wrong. Good old Microsoft has implemented a wonderful inevitable WebHttpBehavior2, which unconditionally adds an internal Microsoft.ServiceModel.Web.WebErrorHandler into the end of endpoint dispatcher error handlers collection. This handler ignores all previously executed handlers and recognizes only a small set of exceptions, while the majority is interpreted as "Internal Server Error", and nothing more.

The question is whether I am on a right path and there is a way to disable this handler in WCF REST mechanism, or introduce it with a new Exception (e.g., when any exception is caught, it is first processed by my handlers and if they throw/return, for instance, FaultException, then this new exception is supplied to Microsoft.ServiceModel.Web.WebErrorHandler instead of the original one). If all my experiments with IErrorHandler and behavior extensions are worthless, what is an alternative? Again, I really do not want to modify the exception throwing logic, I want one place to catch the exceptions and process them.

Thanks a lot!

like image 854
Michael Sagalovich Avatar asked Dec 16 '10 13:12

Michael Sagalovich


2 Answers

When you change the WCF SOAP services to REST, the whole mindset of error reporting and handling changes.

In SOAP, faults are part of your contract. In REST, they simply become codes that you output in the HTTP response code and description.

Here is a catch snippet:

catch (Exception e)
{
    Trace.WriteLine(e.ToString());

    OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
    response.StatusCode = System.Net.HttpStatusCode.UnsupportedMediaType; // or anything you want
    response.StatusDescription = e.Message;
    return null; // I was returning a class
}

So I would suggest you create a helper code which creates relevant error codes for you and put in the response.

like image 96
Aliostad Avatar answered Nov 01 '22 22:11

Aliostad


This what I did in the past

    public class MyServerBehavior : IServiceBehavior {

        public void AddBindingParameters(ServiceDescription serviceDescription,
             ServiceHostBase serviceHostBase, 
             Collection<ServiceEndpoint> endpoints, 
             BindingParameterCollection bindingParameters) {

        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
                                          ServiceHostBase serviceHostBase) {

            foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) {
                chDisp.IncludeExceptionDetailInFaults = true;
                if (chDisp.ErrorHandlers.Count > 0) {
                    // Remove the System.ServiceModel.Web errorHandler
                    chDisp.ErrorHandlers.Remove(chDisp.ErrorHandlers[0]);  
                }
                // Add new custom error handler
                chDisp.ErrorHandlers.Add(new MyErrorHandler());

            }

        }

        public void Validate(ServiceDescription serviceDescription, 
                             ServiceHostBase serviceHostBase) {
        }

    }

MyErrorHandler was my class that implemented IErrorHandler.

like image 22
Darrel Miller Avatar answered Nov 01 '22 22:11

Darrel Miller