12 Stimmen

Elmah protokolliert keine Ausnahmen bei der Verwendung von WebAPI mit HttpResponseException

In meinem WebApi-Code werfe ich eine HttpResponseException, die den Anforderungspipeline umgeht und eine gültige Http-Antwort generiert. Ich versuche jedoch, WebApi mit Elmah-Protokollierung zu integrieren, aber die HttpResponseExeptions werden nicht angezeigt.

Ich habe die web.config für Elmah eingerichtet und folgenden Code:

In Global.asx.cs:

static void ConfigureWebApi(HttpConfiguration config)
{  
    config.Filters.Add(new ServiceLayerExceptionFilter());            
    config.Filters.Add(new ElmahHandledErrorLoggerFilter());
    config.DependencyResolver = new WebApiDependencyResolver(ObjectFactory.Container);                            
}     

Filter:

public class ElmahHandledErrorLoggerFilter : ExceptionFilterAttribute
{
    public override void OnException(HttpActionExecutedContext actionExecutedContext)
    {
        base.OnException(actionExecutedContext);
        ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception);
    }
}

Code, in dem die Ausnahme ausgelöst wird:

public Task UploadFile()
{
    if (Request.Content.IsMimeMultipartContent())
    {                
        var provider = new TolMobileFormDataStreamProvider("C:\images\");

        var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith(
        t =>
        {

            if (t.IsFaulted || t.IsCanceled)
                throw new HttpResponseException(HttpStatusCode.InternalServerError);

            var fileInfo = provider.FileData.FirstOrDefault();
            if (fileInfo == null)
                // die Ausnahme hier wird von Elmah nicht protokolliert?!
                throw new HttpResponseException(HttpStatusCode.InternalServerError);    

            var uploadModel = new FileUpModel { success = true };
            return uploadModel;
        });

        return task;
    }
    else
    {
        throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "Diese Anforderung ist nicht korrekt formatiert"));
    }            
}   

Kann mir jemand, der das zuvor implementiert hat, mitteilen, was ich falsch mache?

11voto

victordscott Punkte 381

Wie oben erwähnt, erfasst der Elmah-Filter nichts, wenn Sie eine HttpResponseException auslösen und protokollieren. Genauer gesagt, wenn die folgende Syntax verwendet wird:

return Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Es war eine schlechte Anfrage");
oder
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "HttpResponseException - Diese Anfrage ist nicht richtig formatiert"));

Ich wollte in beiden Fällen einen Fehler abfangen und protokollieren. Der Weg dazu besteht darin, einen "ActionFilterAttribute" zu verwenden, "OnActionExecuted" zu überschreiben und actionExecutedContext.Response.IsSuccessStatusCode zu überprüfen.

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
    // Wenn actionExecutedContext.Response null ist, wird der Fehler vom Elmah-Filter erfasst und protokolliert
    if ((actionExecutedContext.Response != null) && !actionExecutedContext.Response.IsSuccessStatusCode)
    {
        try
        {
            var messages = (System.Web.Http.HttpError)((System.Net.Http.ObjectContent)actionExecutedContext.Response.Content).Value;
            StringBuilder stringBuilder = new StringBuilder();
            foreach (var keyValuePair in messages) {
                stringBuilder.AppendLine("Nachricht: Schlüssel - " + keyValuePair.Key + ", Wert - " + keyValuePair.Value); 
            }
            Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Web-API-Fehlerstatuscode zurückgegeben - " + stringBuilder.ToString()));
        }
        catch (Exception ex)
        {
            Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Fehler in OnActionExecuted - " + ex.ToString()));
        }
    }
}

Übrigens habe ich auch "OnActionExecuting" überschrieben, um den Modellzustand zu validieren. Dadurch konnte ich alle Überprüfungen in meinen Aktionen entfernen.

public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
{
    if (actionContext.ModelState != null && !actionContext.ModelState.IsValid)
    {
        StringBuilder stringBuilder = new StringBuilder();
        foreach (var obj in actionContext.ModelState.Values)
        {
            foreach (var error in obj.Errors)
            {
                if(!string.IsNullOrEmpty(error.ErrorMessage)) {
                    stringBuilder.AppendLine("Fehler: " + error.ErrorMessage);
                }
            }
        }
        Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception("Ungültiger Modellzustand -- " + stringBuilder.ToString()));
        actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, actionContext.ModelState);
    }
}

Natürlich müssen Sie den Filter mit "config.Filters.Add" hinzufügen.

4voto

Kiran Punkte 56311

Web-API-Sonderfälle HttpResponseException im Action ausgelöst und in HttpResponseMessage umgewandelt und daher wird Ihr Ausnahmefilter nicht aufgerufen.

Dies trifft nicht auf das Werfen von HttpResponseException aus Filtern zu. Im Idealfall sollte man jedoch HttpResponseException nicht aus Filtern werfen, da man eine Anfrage durch Festlegung der Response-Eigenschaft im zugehörigen Eingabekontext abbrechen kann.

3voto

Paige Cook Punkte 22179

Sie müssen Elmah für HttpFilters aktivieren, um dies für WebApi wie erwartet funktionieren zu lassen.

Verwenden Sie Elmah.Contrib.WebApi, das als NuGet Package verfügbar ist. Dort wird eine Klasse hinzugefügt, die Sie dann gemäß den Anweisungen auf der Elmah.Contrib.WebApi-Projektseite verwenden können.

Wenn Sie dies selbst machen möchten, führt Sie Capturing Unhandled Exceptions in ASP.NET Web API's with ELMAH durch, was Elmah.Contrib.WebApi für Sie tut.

Zusätzlich musste ich die Art und Weise ändern, wie die Fehlerantwort geworfen wird, damit sie von Elmah erfasst wird:

 throw new HttpException((int)HttpStatusCode.NotAcceptable, "Diese Anforderung ist nicht korrekt formatiert");

Ich würde auch die Verwendung des Elmah.MVC NuGet Package empfehlen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X