2017-05-24 20 views
1

我正在尝试使用实现IErrorHandler来指示elmah记录未处理的异常。使用IErrorHandler的Elmah日志记录在非WCF项目中实现时不起作用

我在我的解决方案中有多个项目。我有一个实用项目,我已经实现了IErrorHandler。

public abstract class BaseWebServiceErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return false; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     if (error == null) return; 

     if (System.Web.HttpContext.Current == null) 
     { 
      ErrorLog.GetDefault(null).Log(new Error(error)); 
     } 
     else 
     { 
      ErrorSignal.FromCurrentContext().Raise(error); 
     } 
    } 
} 

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) 
    { 
     var errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType); 
     foreach (var channelDispatcherBase in serviceHostBase.ChannelDispatchers) 
     { 
      var channelDispatcher = channelDispatcherBase as ChannelDispatcher; 
      channelDispatcher?.ErrorHandlers.Add(errorHandler); 
     } 
    } 
} 

而在WCF项目,我有哪里我想,当发生未处理的异常,我得到错误与上面的代码使用的服务行为属性

[ServiceErrorBehaviour(typeof(WebServiceErrorHandler))] 
public abstract class BaseWebService : AbstractWebService 
{ 
    public BaseWebService() 
    { 
     //Code logic 
    } 
} 

public class WebServiceErrorHandler : BaseWebServiceErrorHandler 
{ 
} 

现在BaseWebService类之一服务行为不匹配。

但是,当我在我的BaseWebService中定义了IErrorHandler时,它自行工作。

[ServiceErrorBehaviour(typeof(WebServiceErrorHandler))] 
public abstract class BaseWebService : AbstractWebService 
{ 
    public BaseWebService() 
    { 
     //Codelogic 
    } 
} 

//public class WebServiceErrorHandler : BaseWebServiceErrorHandler 
//{ 
//} 

public class WebServiceErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) 
    { 
     return false; 
    } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     if (error == null) return; 

     if (System.Web.HttpContext.Current == null) 
     { 
      ErrorLog.GetDefault(null).Log(new Error(error)); 
     } 
     else 
     { 
      ErrorSignal.FromCurrentContext().Raise(error); 
     } 
    } 
} 

与上述实现它工作良好,并获得在Elmah登录。

我是否在实用程序项目中缺少一些参考? 欣赏你的建议。

+1

我写这篇指南:[登录从WCF ELMAH](https://docs.elmah.io/logging-to-elmah-io-from-wcf /)这可能有所帮助。没有发布这个答案,因为我从来没有用基类测试过。 – ThomasArdal

+0

@ThomasArdal我已经做了类似的实现,但不知道为什么它不能像你所说的那样在基类中工作。 – user824910

回答

1

我刚刚使用这个帖子中的这段代码测试了这个:Logging to ELMAH from WCF

我有两个项目与以下文件:

  • WcfService2
    • BaseService.cs
    • IService1.cs
    • Service1.svc.cs
  • utils的
    • HttpErrorHandler.cs

两个WcfService2和的Utils参考System.ServiceModel.dll,System.ServiceModel.Web.dll和Elmah.dll

这是HttpErrorHandler内容:

using System; 
using System.Collections.ObjectModel; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 

namespace Utils 
{ 
    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. 
      { 
       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 serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, 
      BindingParameterCollection bindingParameters) 
     { 
     } 

     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); 
      } 
     } 
    } 
} 

BaseService.cs:

using Utils; 

namespace WcfService2 
{ 
    [ServiceErrorBehaviour(typeof(HttpErrorHandler))] 
    public class BaseService 
    { 
    } 
} 

最后Service1.svc.cs:

namespace WcfService2 
{ 
    public class Service1 : BaseService, IService1 
    { 
     public string GetData(int value) 
     { 
      var d = 100/value; 
      return string.Format("You entered: {0}", value); 
     } 
    } 
}