The solution from my blog post (referenced in the OP) was based on an existing solution we were/are using to alter HTTP Response Codes during an error state.
So, for us it was a one-line change to pass the Exception to ELMAH. If there's a better solution, I'd love to know about it too.
For Posterity/Reference, and potential improvement - here's the code from the current solution.
HttpErrorHandler and ServiceErrorBehaviourAttribute Classes
using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
/// <summary>
/// Your handler to actually tell ELMAH about the problem.
/// </summary>
public class HttpErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return false;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
if (error != null ) // Notify ELMAH of the exception.
{
if (System.Web.HttpContext.Current == null)
return;
Elmah.ErrorSignal.FromCurrentContext().Raise(error);
}
}
}
/// <summary>
/// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
/// ...and errors reported to ELMAH
/// </summary>
public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
{
Type errorHandlerType;
public ServiceErrorBehaviourAttribute(Type errorHandlerType)
{
this.errorHandlerType = errorHandlerType;
}
public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
IErrorHandler errorHandler;
errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
channelDispatcher.ErrorHandlers.Add(errorHandler);
}
}
}
}
Usage Example
Decorate your WCF Services with the ServiceErrorBehaviour Attribute:
[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
// ...
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…