8

Ich verwende einen globalen Aktionsfilter, um alle Ausnahmen zu behandeln und zu protokollieren. DieseExceptionContext.ExceptionHandled ändert sich in "true". Wo wird die Ausnahme behandelt?

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
    { 
     filters.Add(new ElmahHandleErrorAttribute()); 
     filters.Add(new HandleErrorAttribute()); 
    } 

ist, wie die globalen Aktionsfilter ElmahHandleErrorAttribute definiert - es überschreibt die OnException Methode.

public class ElmahHandleErrorAttribute : System.Web.Mvc.HandleErrorAttribute 
{ 
    public override void OnException(ExceptionContext context) 
    { 
     //Is the exception handled already? context.ExceptionHandled seems to be true here 
     if (!context.IsChildAction && (context.HttpContext.IsCustomErrorEnabled)) 
     { 
      //Do other stuff stuff 
      //Log to Elmah    
     } 
    } 
    ... 
} 

Ich verstehe nicht, warum der Wert von context.ExceptionHandled wahr ist, wenn die OnException Methode ausführt. Wie wird diese Ausnahme behandelt?

-EDIT- Ich habe einen customErrors Abschnitt im Web.Config. Ich habe eine ErrorController Klasse und Aktionen namens General und Http404.

<customErrors mode ="On" defaultRedirect="Error/General"> 
     <error statusCode="404" redirect="Error/Http404"/> 
    </customErrors> 

Was ich nicht verstehe, ist, die Controller-Aktion General nicht ausgeführt wird (Haltepunkt getroffen wird nie), aber der Wert von ExceptionContext.ExceptionHandled auf true gesetzt ist, wenn die OnException Methode der ElmahHandleErrorAttribute beginnt mit der Ausführung.

+0

Ich kann 'context.ExceptionHandled' in Ihrem Code nicht sehen, wo ist es? – gdoron

+0

@gdoron Ich habe den Check für context.ExceptionHandled entfernt.Es war früher in der Anweisung enthalten: 'if (! Context.IsChildAction &&! Context.ExceptionHandled && (context.HttpContext.IsCustomErrorEnabled))' – escist

+0

Haben Sie die OnException-Methode des Controllers überschrieben? – gdoron

Antwort

19

Wenn eine Ausnahme auftritt, wird die Reihenfolge der globalen Filter in reverse order ausgeführt. Dies bedeutet, dass HandleErrorAttribute zuerst ausgeführt wird.

Sie können den Code von HandleErrorAttributehere, aber kurz sehen, es:

  1. ausführt Nur wenn ExceptionHandled falsch ist, und benutzerdefinierte Fehler aktiviert sind.
  2. Richtet eine Weiterleitung an die Fehleransicht ein, die standardmäßig Error heißt.
  3. Stellt ExceptionHandled auf true ein.

Da es der erste Filter ist, dann ExceptionHandled falsch ist, wenn er ausgeführt wird, so dass es die Ansicht setzen und ExceptionHandled auf true Fehler. Wenn also ein eigener Filter ausgeführt wird, ist ExceptionHandled bereits auf true gesetzt. Beachten Sie, dass, wenn benutzerdefinierte Fehler deaktiviert wurden, ExceptionHandled immer noch falsch ist, da HandleErrorAttribute seine Sachen nicht getan hätte. In diesem Fall wird ELMAH den Fehler trotzdem protokollieren, da er nicht behandelt wird (gelber Bildschirm des Todes), sodass der Test in Ihrer Klasse eine doppelte Protokollierung des Fehlers verhindern soll.

Nun zu Ihrer anderen Frage zu Molke die General Aktion nicht ausgeführt wird, wird die defaultRedirect nur verwendet, wenn die Filter nicht setzen einige explizite sich umleiten, es ist so tatsächlich ignoriert, wenn eine Ausnahme innerhalb eines ActionMethod auftritt und Sie haben den globalen Filter HandleErrorAttribute registriert. Es würde jedoch aufgerufen werden, wenn Sie eine URL eingegeben haben, die nicht existiert, d. H. Einen Fehler, der nicht innerhalb einer ActionMethod auftritt. Wenn Sie die Zeile ausmerzen, um die HandleErrorAttribute in Global.asax.cs zu registrieren, erhalten Sie immer die General Controller-Aktion, die ausgeführt wird.

+0

Vielen Dank für Ihre Erklärung. Es hat mir wirklich geholfen. Ich möchte, dass ElmahHandleErrorAttribute der erste ausführbare Filter ist. Würde das Festlegen der Reihenfolge dieses benutzerdefinierten Filters dies beheben? Laut diesem Kommentar (http://stackoverflow.com/a/9163926/1242061) sollte ich dem Filter, den ich zuerst ausführen möchte, einen höheren Bestellwert geben. – escist

+1

Ja, ich vermute, du könntest mit der Order-Eigenschaft herumspielen (aber nicht sicher, wie man das auf einem globalen Filter macht, habe das nur getan, wenn man es als Attribut benutzt). Einfach die Reihenfolge umkehren, die Filter in RegisterGlobalFilters hinzufügen sollte funktionieren ... wenn ein Fehler auftritt, wird der zuletzt hinzugefügte zuerst ausgeführt. Nicht sicher, warum Sie möchten, dass ELMAH zuerst ausgeführt wird, und wenn Sie das wirklich tun, können Sie nicht nach ExceptionHandled suchen, da es in diesem Fall immer falsch ist. –

+0

Ich habe die Reihenfolge bei der Registrierung der Filter angegeben. Jetzt bearbeitet mein benutzerdefinierter Filter "ElmahHandleErrorAttribute" den Fehler zuerst. In Bezug auf Ihre Frage _Nicht sicher, warum Sie möchten, dass die ELMAH zuerst läuft_, Denken Sie, das ist eine schlechte Idee? Ich mache das, weil ich benutzerdefinierte Fehlerseiten anzeigen und den Fehlertyp überprüfen und eine bestimmte Ansicht anzeigen möchte. – escist