我们正在使用优秀的ELMAH处理 ASP.NET 3.5 Web 应用程序中未处理的异常。这对于除使用 REST 功能使用的 WCF 服务之外的所有站点都非常有效。当操作方法中发生应用程序代码未处理的异常时,WCF 根据服务契约和配置设置以各种方式进行处理。这意味着该异常最终不会触发 ELMAH 的 ASP.NET HttpApplication.Error 事件。用途。我知道处理这个问题的两个解决方案是:
- 将所有方法调用包装在 try { } catch(Exception ex) { Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 中扔; } 在 catch block 中显式调用 Elmah。
- 使用IErrorHandler如 Will Hughes' 中所述博客文章 Making WCF and ELMAH play nice together将对 ELMAH 的调用分解为单独的 ErrorHandler。
第一个选项非常简单,但并不完全是 DRY 。第二个选项只需要您在实现属性和 ErrorHandler 后使用自定义属性来装饰每个服务。我是根据 Will's 这样做的工作,但我想在发布代码之前验证这是正确的方法。
有我错过的更好的方法吗?
IErrorHandler 的 MSDN 文档说 HandleError 方法是进行日志记录的地方,但是 ELMAH访问 HttpContext.Current.ApplicationInstance,即使 HttpContext.Current 可用,该方法在此方法中仍为 null。在 ProvideFault 方法中调用 Elmah 是一种解决方法,因为已设置 ApplicationInstance,但这与 API 文档中描述的意图不符。 我在这里遗漏了什么吗?文档确实指出您不应该依赖在操作线程上调用的 HandleError 方法,这可能就是 ApplicationInstance 在此范围内为 null 的原因。
最佳答案
我的博客文章中的解决方案(在 OP 中引用)基于我们曾经/正在用来在错误状态期间更改 HTTP 响应代码的现有解决方案。
因此,对于我们来说,将异常传递给 ELMAH 只需一行更改。如果有更好的解决方案,我也很想知道。
供后代/引用和潜在改进 - 这是当前解决方案的代码。
HttpErrorHandler 和 ServiceErrorBehaviourAttribute 类
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);
}
}
}
}
使用示例
使用 ServiceErrorBehaviour 属性装饰您的 WCF 服务:
[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
// ...
}
关于asp.net - 使用 ELMAH 记录 WCF 服务的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/895901/