Frage

Wir sind mit dem ausgezeichneten ELMAH mit nicht behandelten Ausnahmen in einer ASP.NET 3.5 Web umgehen Anwendung. Das funktioniert sehr gut für alle von der Website abgesehen von WCF-Diensten, die die REST-Funktionen unter Verwendung verbraucht werden. Wenn eine Ausnahme innerhalb der Betriebsmethoden auftritt, die nicht durch den Anwendungscode behandelt wird, behandelt WCF es auf verschiedene Weise auf den Serviceverträge und Konfigurationseinstellungen abhängig. Dies bedeutet, dass die Ausnahme nicht am Ende des ASP.NET HttpApplication.Error Ereignisses Brennen, dass ELMAH Anwendungen . Die beiden Lösungen, die ich bin mir dessen bewusst damit umgehen sind:

  • Wickeln Sie alle Methodenaufrufe in einer try {} catch (Exception ex) {Elmah.ErrorSignal.FromCurrentContext () anheben (ex). werfen; } Explizit Elmah im catch-Block aufrufen.
  • Verwenden Sie IErrorHandler wie in < a href = "http://will.hughesfamily.net.au/about/" rel = "noreferrer"> Will Hughes' Blogeintrag macht WCF und ELMAH spielen schön zusammen, um den Anruf zu ELMAH zu einem separaten Fehlerbehandler ausklammern.

Die erste Option ist extrem einfach, aber ist nicht genau DRY . Die zweite Option erfordert, dass Sie nur jeden Dienst mit dem benutzerdefinierten Attribute dekoriert nach dem Attribute und den Fehlerbehandler implementieren. Ich habe dies auf Wills Arbeit, aber ich möchte, um zu überprüfen, dass dies die ist richtiger Ansatz , bevor Sie den Code veröffentlichen.

Gibt es eine bessere Art und Weise, die ich verpasst habe?

Die MSDN documenation für IErrorHandler sagt dass die Handle Methode ist der Ort, um die Protokollierung zu tun, aber ELMAH Zugriffe die HttpContext.Current. ApplicationInstance , die innerhalb dieser Methode null ist, obwohl HttpContext.Current verfügbar ist. Macht den Anruf zu Elmah innerhalb der ProvideFault Methode ist eine Abhilfe als ApplicationInstance gesetzt ist, aber dies nicht die Absicht, in der API-Dokumentation beschrieben entspricht. Bin ich etwas fehlt hier? In der Dokumentation wird, dass Sie nicht auf dem Handle Methode verlassen sollte auf den Betrieb Thread aufgerufen wird, die sein kann, warum ApplicationInstance in diesem Bereich null ist.

War es hilfreich?

Lösung

Die Lösung von meiner Blog-Post (im OP bezeichnet) wurde auf einer bestehende Lösung auf Basis wir / verwenden, um HTTP-Response-Codes während eines Fehlerzustandes zu ändern.

Also, für uns war es eine einzeilige Änderung die Ausnahme ELMAH passieren. Wenn es eine bessere Lösung ist, würde ich gerne auch darüber Bescheid wissen.

Für die Nachwelt / Reference und mögliche Verbesserung - hier ist der Code aus der aktuellen Lösung.

HttpErrorHandler und ServiceErrorBehaviourAttribute Klassen

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

Verwendung Beispiel

Ihre WCF Service mit dem ServiceErrorBehaviour Attribute Verzieren:

[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
  // ...
}

Andere Tipps

Wenn Sie ein BehaviorExtensionElement Erstellung ist es sogar möglich, das Verhalten mit Config zu aktivieren:

public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(ServiceErrorBehaviourAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
    }
}

Config:

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <elmah />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

Auf diese Weise ist es auch möglich ELMAH in Kombination mit RIA-Diensten zu nutzen!

  

Ich habe diese Arbeit basiert auf Wille geschehe   aber ich möchte, um zu überprüfen, dass dies die   richtiger Ansatz vor der Entsendung   Code.

Ich denke, das ist ein großer Ansatz (ein dickes Lob an für diesen Beitrag!). Ich glaube nicht, Will oder Sie haben hier etwas verpasst. Ausführungs IErrorHandler ist der bevorzugte Weg, um alle möglichen serverseitige Ausnahmen für den Fang, die sonst den Kommunikationskanal dazu führen könnten, bemängelt werden (abgerissen) und somit ist es ein natürlicher Ort in einiger Protokollierung wie ELMAH einzuzuhaken.

Marc

Das kann gut für einige Leute offensichtlich sein, aber ich schon eine ganze Weile nur damit verbracht, herauszufinden, warum mein HttpContext.Current trotz folgenden alles ausgezeichneten Antwort Will Hughes' null war. Embarassingly, erkennen ich, dass dies, weil mein WCF-Dienst von einer MSMQ Nachricht aktiviert wird.

Ich landete die ProvideFault() Methode Umschreiben:

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

Ich war nicht in der Lage, die vorgeschlagene Antwort zu bekommen mit einem WCF Data Service arbeiten. Ich telegraphierte das Verhalten Attribut up, etc, aber immer noch nicht bekommen haben protokolliert alle Fehler. Stattdessen landete ich folgendes an die Service-Implementierung Aufsummierung:

protected override void HandleException(HandleExceptionArgs args)
{
    Elmah.ErrorSignal.FromCurrentContext().Raise(args.Exception);
    base.HandleException(args);
}

Ich habe nicht versucht dies ausdrücklich mit dem REST-Zeug zu tun, und nicht verwendet ELMAH mich, aber eine weitere Option lohnt ein Blick in sein könnte in WCF Haken mit einem IDispatchMessageInspector anstelle eines IErrorHandler.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top