2017-05-24 45 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); 
     } 
    } 
}