Quali sono le linee guida definitive per la gestione personalizzata degli errori in ASP.NET MVC 3?


44

Il processo di gestione degli errori personalizzati in ASP.NET MVC (3 in questo caso) sembra essere incredibilmente trascurato. Ho letto le varie domande e risposte qui, sul web, le pagine di aiuto per vari strumenti (come Elmah), ma mi sento come se fossi andato in un cerchio completo e ancora non avessi la soluzione migliore. Con il tuo aiuto, forse possiamo stabilire un nuovo approccio standard per la gestione degli errori. Vorrei mantenere le cose semplici e non progettare troppo.

Ecco i miei obiettivi:

Per errori / eccezioni del server:

  1. Visualizza le informazioni di debug in dev
  2. Visualizza la pagina di errore descrittiva in produzione
  3. Registrare gli errori e inviarli via e-mail all'amministratore in produzione
  4. Restituisce 500 codice di stato HTTP

Per errori 404 non trovati:

  1. Visualizza la pagina di errore descrittiva
  2. Registrare gli errori e inviarli via e-mail all'amministratore in produzione
  3. Restituisce 404 codice di stato HTTP

C'è un modo per raggiungere questi obiettivi con ASP.NET MVC?


2
Vorrei che questa domanda venisse migrata TORNA A SO in modo da poter ottenere più risposte. Sto cercando risposte in codice.
Shawn Mclean,

@Shawn È improbabile che accada. La domanda è più sull'argomento qui che su SO e ha una risposta accettata. Inoltre, le domande in genere non vengono nuovamente migrate per motivi tecnici. Se hai bisogno di aiuto con la codifica di un approccio specifico alla gestione degli errori, apri una nuova domanda su StackOverflow. Altrimenti, "risposte codificate" potrebbe essere un criterio troppo ampio per essere utile o rispondibile. Ultimo ma non meno importante, il modo migliore per attirare l'attenzione del moderatore su una domanda è di contrassegnarla. Il tuo commento qui probabilmente sarebbe passato inosservato se non inciampasse in un auto-flag spingendo il conteggio dei commenti su 20.
Adam Lear

C'erano circa 10 commenti qui, dove sarebbero andati tutti?
RyanW,

Ho trovato una soluzione che soddisfa i tuoi obiettivi. Ho un'altra risposta su SO: stackoverflow.com/questions/6508415/…
Jesse Webb,

1
@AnnaLear Concordo con Shawn. Ho trovato questa pagina solo tramite Google. Si noti che quasi tutte le risposte di seguito contengono collegamenti INDIETRO a StackTranslate.it. Per me che parla di volumi, in quanto avrebbe dovuto essere lasciato lì in primo luogo.
Rebecca,

Risposte:


23

Condividerò il modo in cui ho finito per farlo, che faceva parte della domanda originale.

Innanzitutto, i problemi che ho riscontrato:

  1. Con customErrors su (cioè in produzione) l' HandleErrorattributo globale ingoia le eccezioni e rende la tua visualizzazione degli errori, ma poi non puoi registrarla con uno strumento di addon come elmah, poiché elmah non lo vede mai. Potresti registrarlo a tuo avviso, suppongo, ma è una vista, che sembra sbagliata. L'attributo globale HandleError appare nuovo nel modello di progetto MVC 3 RTM Visual Studio.

  2. customErrors con URL per endpoint MVC restituisce 302 codici di stato. Esiste la proprietà redirectmode, ma non è possibile abbinare gli URL mvc in customErrors e utilizzare la modalità ResponseRewrite. ( https://stackoverflow.com/questions/781861/customerrors-does-not-work-when-setting-redirectmode-responserewrite/3770265#3770265 )

  3. Evitare completamente gli errori personalizzati e gestire tutto ciò che è personalizzato nella tua app comporta molta complessità, IMO. (Mi è piaciuto molto: https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404s-in-asp-net-mvc/2577095#2577095 , ma non era adatto al nostro progetto)

La mia soluzione

Ho rimosso completamente MVC dall'equazione. Ho rimosso HandleErrorAttributeil filtro globale in global.asax e mi sono concentrato interamente sulla configurazione customErrors, spostandolo per utilizzare i reindirizzamenti WebForm e passare alla modalità di reindirizzamento ResponseRewritein per evitare i codici di risposta HTTP 302.

<customErrors mode="On" defaultRedirect="/Error.aspx" redirectMode="ResponseRewrite">
  <error statusCode="404" redirect="/NotFound.aspx" />
</customErrors>

Quindi, NotFound.aspxnell'evento page_load, imposta Response.StatusCode404 e in Error.aspx imposta il codice 500.

risultati:

Gli obiettivi per entrambi sono stati raggiunti con i registri Elmah, la pagina di errore descrittiva e il codice di stato con una riga di codice sui code-behind. Non lo stiamo facendo come "MVC Way" come fa la soluzione precedente, ma sono d'accordo se si tratta di due righe di codice.


5

Penso che MVC, ASP e il tuo framework preferito per la registrazione / gestione delle eccezioni possano gestire i tuoi obiettivi abbastanza bene. ELMAH ed Enterprise Library forniscono entrambi una gestione delle eccezioni e una registrazione facili da usare, quindi scegli il tuo preferito ... Non ho intenzione di andare sui pro e contro di ciascuno qui.

NOTA: non è possibile visualizzare una pagina di errore intuitiva E restituire un HTTP 404 o 500 come suggerisce la domanda. Quando si restituisce una pagina di errore descrittiva, il codice HTTP restituito al browser sarà 302. Si tratta di un reindirizzamento alla pagina di segnalazione descrittiva.

Pagine di errore amichevoli

Sembra che tu possa raggiungere i tuoi obiettivi dalle buone impostazioni web.config vecchio stile che fanno parte di ASP.net da qualche tempo. Si menziona la visualizzazione delle informazioni di debug durante lo sviluppo e la visualizzazione di pagine amichevoli in produzione. A tale scopo è possibile utilizzare la sezione degli errori personalizzati di web.config (Impostare CustomErrors = "Off" per mostrare le informazioni di debug). Presumo che tu abbia familiarità con l'attributo CustomErrors, se non leggi questo:

http://msdn.microsoft.com/en-us/library/h0hfz6fc.aspx

Se è necessaria una maggiore granularità di controllo sulle visualizzazioni degli errori visualizzate, utilizzare l'attributo HandleError di MVC. In questo modo è possibile scegliere diverse visualizzazioni di errore per ciascuna azione / controller.

http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx

Registrazione delle eccezioni

Sembra che tu voglia rispondere a tutte le tue eccezioni allo stesso modo ("Registra errori e inviali via e-mail all'amministratore in produzione"). In questo caso, l'opzione più semplice è aggiungere il codice

Application_Error (mittente oggetto, EventArgs e)

nel tuo global.asax. Qui è possibile passare al framework di registrazione scelto.

Se si desidera un maggiore controllo sulla registrazione / gestione delle eccezioni, è possibile sottoclassare HandleErrorAttribute e sovrascrivere

OnException(System.Web.Mvc.ExceptionContext filterContext)

questo è un altro posto in cui è possibile passare al framework di registrazione scelto.

https://stackoverflow.com/questions/183316/asp-net-mvc-handleerror

Questo ti dà un maggiore controllo rispetto alla tecnica Application_Error menzionata sopra.

In generale MVC offre una granularità di controllo su come gestire gli errori. Se non hai bisogno di questo controllo, puoi ricorrere ai modi ASP.net di fare cose come la definizione di pagine di errore sul tuo web.config.


Grazie mille per aver aggiunto i tuoi pensieri. Penso che il codice di stato 302 sia una cattiva scelta di progettazione da parte del team ASP.NET originale. Lo affronterò anche nelle mie risposte, ci sono alcune opzioni per farlo. Sembra che alcuni nel mondo MVC stiano abbandonando completamente CustomErrors e gestendo tutto nell'app per una migliore riusabilità e un maggiore controllo, come sottolineato. Ma ho avuto un successo limitato nell'implementare quelli e stavo aggiungendo un sacco di codice che sembrava essere meglio cotto. Più nelle mie risposte di seguito.

Preferisco sovrascrivere il metodo OnException per la registrazione, in questo modo so di poter registrare tutto, anche l'errore che si verifica da una chiamata Ajax che trovo non attiverà il tuo Application_Error.
Alicia,

@Alicia codice di esempio completo?
Kiquenet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.