8

Sto utilizzando un filtro azione globale per gestire e registrare tutte le eccezioni.ExceptionContext.ExceptionHandled passa a true. Dove viene gestita l'eccezione?

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

Questo è come il filtro di azione globale ElmahHandleErrorAttribute è definito - è l'override del metodo OnException.

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    
     } 
    } 
    ... 
} 

Non capisco il motivo per cui il valore di context.ExceptionHandled è vero quando il metodo OnException esegue. Come viene gestita questa eccezione?

operativa -Editazione- Ho una sezione customErrors nel Web.Config. Ho una classe ErrorController e azioni chiamate General e Http404.

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

Quello che non capisco è, l'azione di controllo General non viene eseguita (punto di interruzione non è mai colpito), ma il valore di ExceptionContext.ExceptionHandled è impostata su true quando il metodo di ElmahHandleErrorAttribute inizia OnException esecuzione.

+0

Non riesco a vedere 'context.ExceptionHandled' nel codice, dove si trova? – gdoron

+0

@gdoron Ho rimosso il controllo per context.ExceptionHandled.È stato precedentemente incluso nell'istruzione: 'if (! Context.IsChildAction &&! Context.ExceptionHandled && (context.HttpContext.IsCustomErrorEnabled))' – escist

+0

Hai sovrascritto il metodo 'OnException' del controller? – gdoron

risposta

19

Quando si verifica un'eccezione, l'ordine dei filtri globali viene eseguito in reverse order. Ciò significa che HandleErrorAttribute viene eseguito per primo.

È possibile visualizzare il codice di HandleErrorAttributehere, ma in breve, è:

  1. eseguito solo se ExceptionHandled è falso, e gli errori personalizzati sono abilitati.
  2. Imposta un reindirizzamento alla visualizzazione errori, che per impostazione predefinita è denominata Error.
  3. Imposta su ExceptionHandled su true.

Come è il primo filtro, quindi ExceptionHandled è falso quando esegue, facendolo impostare la visualizzazione di errore e impostando ExceptionHandled true. Quindi, quando il tuo filtro viene eseguito, è per questo che ExceptionHandled è già impostato su true. Si noti che se gli errori personalizzati sono stati disabilitati, quindi ExceptionHandled sarebbe ancora falso, come HandleErrorAttribute non avrebbe fatto la sua roba. In questo caso, ELMAH registrerà comunque l'errore, in quanto non gestito (schermo giallo della morte), quindi il test della classe serve a impedire la registrazione duplicata dell'errore.

Ora, al vostro altra domanda circa il siero di latte non viene eseguita l'azione General, il defaultRedirect viene utilizzato solo se i filtri non impostare alcuni esplicita stessi redirect, quindi in realtà è ignorato quando si verifica un'eccezione all'interno di un ActionMethod e hai il filtro globale HandleErrorAttribute registrato. Sarebbe tuttavia chiamato se inserissi un URL che non esisteva, cioè un errore che non si verifica da un ActionMethod. Inoltre, se commentate la linea per registrare lo HandleErrorAttribute in Global.asax.cs, otterrete sempre l'esecuzione dell'azione del controller General.

+0

Grazie per la spiegazione. Mi ha davvero aiutato. Voglio che ElmahHandleErrorAttribute sia il primo filtro che viene eseguito. L'impostazione di questo filtro personalizzato sarebbe stata corretta? Come da questo commento (http://stackoverflow.com/a/9163926/1242061) dovrei dare un valore di ordine superiore al filtro che voglio eseguire prima. – escist

+1

Sì, ho il sospetto che tu possa giocare con la proprietà Order (ma non sei sicuro di come farlo su un filtro globale, lo hai fatto solo quando lo usi come attributo). Semplicemente invertendo l'ordine si aggiungono i filtri in RegisterGlobalFilters dovrebbe funzionare ... quando si verifica un errore, l'ultimo aggiunto verrà eseguito per primo. Non sono sicuro del motivo per cui si dovrebbe eseguire l'ELMAH prima, e se lo si fa davvero, non è possibile cercare ExceptionHandled poiché in tal caso sarà sempre falso. –

+0

Ho specificato gli ordini durante la registrazione dei filtri. Ora il mio filtro personalizzato 'ElmahHandleErrorAttribute' sta gestendo prima l'errore. Per quanto riguarda la tua domanda _Non sono sicuro del motivo per cui vorrai che l'ELMAH sia il primo a correre, però, pensi che questa sia una cattiva idea? Lo sto facendo perché voglio visualizzare pagine di errore personalizzate e controllare il tipo di errore e visualizzare una vista specifica. – escist

Problemi correlati