How do I create a global exception handler for a WCF Services?

Viewed 29390

I want to log all exceptions server side.

In ASP.NET I write something like this in Global.asax.cs, but will this work for a WCF service, too?

public class Global : HttpApplication
{
    protected void Application_Error(object sender, EventArgs e)
    {
        Exception unhandledException = Server.GetLastError();

        //Log exception here
        ...
    }
} 

UPDATE: I don't want to have a try...catch for every [OperationContract] in my .svc file. I short... I want to make sure that all exception that my service throws is logged by log4net. I'm not talking about how the client handles exception.

4 Answers

You can create a WCF error-logger by implementing IErrorHandler and associating it with the service; typically (for logging) you would return false from HandleError (allowing other handlers to execute), and log the error either in HandleError (using the Exception) or in ProvideFault (using the ref Message fault).

I apply this handler by writing a custom behavior (inheriting from BehaviorBase), which (in ApplyDispatchBehavior) adds the error-handler to endpointDispatcher.ChannelDispatcher.ErrorHandlers if it isn't already there.

The behavior can be applied via configuration.

I followed the sample but I found an annoying error that happened even if I just try to use the following statement in a Web Method of my WCF Service:

string myTypeName = typeof(ErrorHandlerBehavior).AssemblyQualifiedName;

where ErrorHandlerBehavior derives from BehaviorExtensionElement.

The line works well when I test the service on my localhost. On the web, the call of the containing method raises the Exception "Access is denied".

In this case, I guess that the cause was that my IP does not allow the creation of a BehaviourExtensionElement in a Partially Trusted environment (my service is in a shared hosting environment).

Finally, I succeded following the first mechanism described at https://docs.microsoft.com/en-us/dotnet/framework/wcf/extending/configuring-and-extending-the-runtime-with-behaviors about Service Behaviors:

"Using an attribute on the service class. When a ServiceHost is constructed, the ServiceHost implementation uses reflection to discover the set of attributes on the type of the service. If any of those attributes are implementations of IServiceBehavior, they are added to the behaviors collection on ServiceDescription. This allows those behaviors to participate in the construction of the service run time."

This allowed me to avoid the definition and the creation of the BehaviorExtensionElement.

I just modified the derivation (no other modification required):

public class ErrorServiceBehavior : Attribute, IServiceBehavior
{ ... }

and use the class as Attribute of my service:

[ErrorServiceBehavior()]
public partial class MyService : IMyService
{...}

No other modification required.

Related