AGGIORNAMENTO
Poiché questa risposta fornisce una soluzione, non la modificherò, ma ho trovato un modo molto più pulito per risolvere questo problema. Vedi la mia altra risposta per i dettagli ...
Risposta originale:
ho capito perché il Application_Error()
metodo non viene invocato ...
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
Per impostazione predefinita (quando viene generato un nuovo progetto), un'applicazione MVC ha una logica nel Global.asax.cs
file. Questa logica viene utilizzata per mappare le rotte e registrare i filtri. Per impostazione predefinita, registra solo un filtro: un HandleErrorAttribute
filtro. Quando customErrors è attivo (o tramite richieste remote quando è impostato su RemoteOnly), HandleErrorAttribute indica a MVC di cercare una visualizzazione Error e non chiama mai il Application_Error()
metodo. Non sono riuscito a trovare la documentazione di questo, ma è spiegato in questa risposta su programmers.stackexchange.com .
Per ottenere il metodo ApplicationError () chiamato per ogni eccezione non gestita, rimuovere semplicemente la riga che registra il filtro HandleErrorAttribute.
Ora il problema è: come configurare customErrors per ottenere ciò che desideri ...
Il valore predefinito della sezione customErrors è redirectMode="ResponseRedirect"
. È possibile specificare anche l'attributo defaultRedirect come route MVC. Ho creato un ErrorController che era molto semplice e ho cambiato il mio web.config in questo modo ...
web.config
<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
Il problema con questa soluzione è che esegue un reindirizzamento 302 agli URL di errore e quindi quelle pagine rispondono con un codice di stato 200. Questo porta a Google che indicizza le pagine di errore che è male. Inoltre non è molto conforme alle specifiche HTTP. Quello che volevo fare non era reindirizzare e sovrascrivere la risposta originale con le mie visualizzazioni di errore personalizzate.
Ho provato a cambiare redirectMode="ResponseRewrite"
. Sfortunatamente, questa opzione non supporta route MVC , solo pagine HTML statiche o ASPX. All'inizio ho provato a utilizzare una pagina HTML statica ma il codice di risposta era ancora 200 ma, almeno, non ha reindirizzato. Allora ho avuto un'idea da questa risposta ...
Ho deciso di rinunciare a MVC per la gestione degli errori. Ho creato un Error.aspx
e un file PageNotFound.aspx
. Queste pagine erano molto semplici ma avevano un pezzo di magia ...
<script type="text/C#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
}
</script>
Questo blocco indica alla pagina di essere servita con il codice di stato corretto. Di grossolano, nella pagina PageNotFound.aspx, ho usato HttpStatusCode.NotFound
invece. Ho cambiato il mio web.config in questo modo ...
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
Ha funzionato tutto perfettamente!
Sommario:
- Rimuovi la riga:
filters.Add(new HandleErrorAttribute());
- Usa il
Application_Error()
metodo per registrare le eccezioni
- Usa customErrors con ResponseRewrite, che punta alle pagine ASPX
- Rendere le pagine ASPX responsabili dei propri codici di stato della risposta
Ci sono un paio di aspetti negativi che ho notato con questa soluzione.
- Le pagine ASPX non possono condividere alcun markup con i modelli Razor, ho dovuto riscrivere il markup standard di intestazione e piè di pagina del nostro sito Web per un aspetto coerente.
- È possibile accedere alle pagine * .aspx direttamente premendo i relativi URL
Ci sono soluzioni per questi problemi, ma non ero abbastanza preoccupato per fare alcun lavoro extra.
Spero che questo possa aiutare tutti!