2017-05-24 2 views
1

Ich versuche, mit dem Tool IErrorHandler zu signalisieren, elmah nicht behandelte Ausnahmen zu protokollieren.Elmah-Protokollierung mit IErrorHandler funktioniert nicht, wenn in nicht WCF-Projekt implementiert

Ich hatte mehrere Projekte in meiner Lösung. Ich habe ein Dienstprogramm-Projekt, wo ich IErrorHandler implementiert habe.

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

Und in eines des WCF Projekt, das ich eine BaseWebService Klasse, wo ich das Betriebsverhalten zu verwenden versuchen Attribut

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

public class WebServiceErrorHandler : BaseWebServiceErrorHandler 
{ 
} 

nun mit dem obigen Code, wenn eine nicht behandelte Ausnahme, die ich Störung erhalte auftritt dass das Dienstverhalten nicht übereinstimmt.

aber wenn ich die Definition von IErrorHandler in meinem BaseWebService habe, funktioniert es.

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

mit der obigen Implementierung funktioniert es gut und wird in Elmah auch eingeloggt.

Fehle ich eine Referenz im Utility-Projekt? Schätzen Sie Ihre Vorschläge.

+1

Ich schrieb dieses Handbuch: [zu ELMAH von WCF Logging] (https://docs.elmah.io/logging-to-elmah-io-from-wcf /) was helfen kann. Ich poste das nicht als Antwort, da ich das nie mit Basisklassen getestet habe. – ThomasArdal

+0

@ThomasArdal Ich habe eine ähnliche Implementierung gemacht, aber nicht sicher, warum es nicht mit der Basisklasse funktioniert, wie Sie gesagt haben. – user824910

Antwort

1

Ich habe dies gerade mit diesem Code von diesem Beitrag getestet: Logging to ELMAH from WCF.

Ich habe zwei Projekte mit den folgenden Dateien:

  • WcfService2
    • BaseService.cs
    • IService1.cs
    • Service1.svc.cs
  • Utils
    • HttpErrorHandler.cs

Sowohl WcfService2 und Utils Referenz System.ServiceModel.dll, System.ServiceModel.Web.dll und Elmah.dll

Dies ist der Inhalt in 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 
    { 
    } 
} 

und schließlich 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); 
     } 
    } 
} 
Verwandte Themen