我们正在使用优秀的ELMAH http://code.google.com/p/elmah处理 ASP.NET 3.5 Web 应用程序中未处理的异常。这对于除使用 REST 功能使用的 WCF 服务之外的所有站点都非常有效。当操作方法中发生应用程序代码未处理的异常时,WCF 根据服务契约和配置设置以各种方式进行处理。这意味着异常最终不会触发 ASP.NET HttpApplication.Error 事件ELMAH http://code.google.com/p/elmah用途。我知道处理这个问题的两个解决方案是:
- 将所有方法调用包装在 try { } catch(Exception ex) { Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 中扔;在 catch 块中显式调用 Elmah。
- Use 错误处理程序 http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx如中所述威尔·休斯的 http://will.hughesfamily.net.au/about/博客文章让 WCF 和 ELMAH 和谐相处 http://will.hughesfamily.net.au/20090505/making-wcf-and-elmah-play-nice-together/将对 ELMAH 的调用分解为单独的 ErrorHandler。
第一个选项非常简单,但并不完全是DRY http://en.wikipedia.org/wiki/Don't_repeat_yourself。第二个选项只需要您在实现属性和 ErrorHandler 后使用自定义属性来装饰每个服务。我这样做是基于Will's http://will.hughesfamily.net.au/about/工作,但我想验证这是正确的做法在发布代码之前。
有没有我错过的更好的方法?
MSDN 文档错误处理程序 http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx说处理错误方法是进行日志记录的地方,但是ELMAH http://code.google.com/p/elmah访问 HttpContext.Current。应用程序实例,即使 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
{
// ...
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)