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.
Adding a Global Exception HandlerIn the Design tab part of the Ribbon, select New > Global Handler. The New Global Handler window opens. Type in a Name for the handler and save it in the project path. Click Create, a Global Exception Handler is added to the automation project.
Handling exceptions globally Another way to handle exceptions in WCF is by implementing the IErrorHandler interface on your service class to handle all exceptions globally and provide a SOAP compliant FaultException. This interface contains two methods -- HandleError and ProvideFault.
Advertisements. A WCF service developer may encounter some unforeseen errors which require reporting to the client in a suitable manner. Such errors, known as exceptions, are normally handled by using try/catch blocks, but again, this is very technology specific.
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.
This is not an answer itself, but an addendum to the great answer provided by SkyBlade002, providing the given code in C#, for convenience for any C# coder:
Here's my code (in ErrorHandler.cs):
/// <summary> /// This class defines a global ErrorHandler, that allows us to control the fault message returned to the client and /// perform custom error processing like logging. /// </summary> public class ErrorHandler : IErrorHandler { private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); /// <summary> /// Enables the creation of a custom <see cref="T:System.ServiceModel.FaultException`1" /> that is returned from an /// exception in the course of a service method. /// </summary> /// <remarks> /// This method is optionally used to transform standard exceptions into custom FaultException(Of TDetail) that /// can be passed back to the service client. /// </remarks> /// <param name="error">The <see cref="T:System.Exception" /> object thrown in the course of the service operation.</param> /// <param name="version">The SOAP version of the message.</param> /// <param name="fault"> /// The <see cref="T:System.ServiceModel.Channels.Message" /> object that is returned to the client, or /// service, in the duplex case. /// </param> public void ProvideFault(Exception error, MessageVersion version, ref Message fault) {} /// <summary> /// This method will be called whenever an exception occurs. Therefore, /// we log it and then return false so the error can continue to propagate up the chain. /// </summary> /// <param name="error">Exception being raised.</param> /// <returns>False to let the error propagate up the chain, or True to stop the error here.</returns> public bool HandleError(Exception ex) { Log.Error(ex); //TODO your own logging return false; }
Here's my code (in ErrorHandlerBehavior.cs):
/// <summary> /// This class defines a BehaviorExtensionElement, so that we can use the ErrorServiceBehavior class, defined above, in /// our App.config. /// </summary> public class ErrorHandlerBehavior : BehaviorExtensionElement { /// <summary> /// Gets the type of behavior. /// </summary> public override Type BehaviorType { get { return typeof (ErrorServiceBehavior); } } /// <summary> /// Creates a behavior extension based on the current configuration settings. /// </summary> /// <returns> /// The behavior extension. /// </returns> protected override object CreateBehavior() { return new ErrorServiceBehavior(); } }
Here's my code (in ErrorServiceBehavior.cs):
/// <summary> /// This class defines a ServiceBehavior, that will allow us to add our custom ErrorHandler class, defined above, to /// each channel we have a service running on. /// </summary> public class ErrorServiceBehavior : IServiceBehavior { /// <summary> /// Provides the ability to inspect the service host and the service description to confirm that the service can run /// successfully. /// </summary> /// <param name="serviceDescription">The service description.</param> /// <param name="serviceHostBase">The service host that is currently being constructed.</param> public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) {} /// <summary> /// Provides the ability to pass custom data to binding elements to support the contract implementation. /// </summary> /// <param name="serviceDescription">The service description of the service.</param> /// <param name="serviceHostBase">The host of the service.</param> /// <param name="endpoints">The service endpoints.</param> /// <param name="bindingParameters">Custom objects to which binding elements have access.</param> public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) {} /// <summary> /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, /// message or parameter interceptors, security extensions, and other custom extension objects. /// </summary> /// <param name="serviceDescription">The service description.</param> /// <param name="serviceHostBase">The host that is currently being built.</param> public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { //Enumerate all channels and add the error handler to the collection var handler = new ErrorHandler(); foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) { dispatcher.ErrorHandlers.Add(handler); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With