UPDATE
Da diese Antwort eine Lösung bietet, werde ich sie nicht bearbeiten, aber ich habe einen viel saubereren Weg gefunden, um dieses Problem zu lösen. Siehe meine andere Antwort für Details ...
Ursprüngliche Antwort:
Ich habe herausgefunden, warum die Application_Error()
Methode nicht aufgerufen wird ...
Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute()); // this line is the culprit
}
...
}
Standardmäßig (wenn ein neues Projekt generiert wird) enthält eine MVC-Anwendung eine Logik in der Global.asax.cs
Datei. Diese Logik wird zum Zuordnen von Routen und zum Registrieren von Filtern verwendet. Standardmäßig wird nur ein Filter registriert: ein HandleErrorAttribute
Filter. Wenn customErrors aktiviert ist (oder über Remote-Anforderungen, wenn RemoteOnly festgelegt ist), weist das HandleErrorAttribute MVC an, nach einer Fehleransicht zu suchen, und ruft die Application_Error()
Methode niemals auf . Ich konnte keine Dokumentation dazu finden, aber diese wird in dieser Antwort auf programmers.stackexchange.com erläutert .
Um die ApplicationError () -Methode für jede nicht behandelte Ausnahme aufzurufen, entfernen Sie einfach die Zeile, in der der HandleErrorAttribute-Filter registriert ist.
Das Problem ist nun: So konfigurieren Sie die customErrors, um das zu erhalten, was Sie möchten ...
Der Abschnitt customErrors ist standardmäßig redirectMode="ResponseRedirect"
. Sie können das Attribut defaultRedirect auch als MVC-Route angeben. Ich habe einen ErrorController erstellt, der sehr einfach war, und meine web.config so geändert, dass sie so aussieht ...
web.config
<customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
<error statusCode="404" redirect="~/Error/PageNotFound" />
</customErrors>
Das Problem bei dieser Lösung besteht darin, dass eine 302-Umleitung zu Ihren Fehler-URLs durchgeführt wird und diese Seiten dann mit einem 200-Statuscode antworten. Dies führt dazu, dass Google die Fehlerseiten indiziert, was schlecht ist. Es ist auch nicht sehr konform mit der HTTP-Spezifikation. Ich wollte nicht umleiten und die ursprüngliche Antwort mit meinen benutzerdefinierten Fehleransichten überschreiben.
Ich habe versucht mich zu ändern redirectMode="ResponseRewrite"
. Leider unterstützt diese Option keine MVC-Routen , nur statische HTML-Seiten oder ASPX. Ich habe zuerst versucht, eine statische HTML-Seite zu verwenden, aber der Antwortcode war immer noch 200, aber zumindest wurde er nicht umgeleitet. Ich habe dann eine Idee von dieser Antwort ...
Ich habe mich entschlossen, MVC wegen Fehlerbehandlung aufzugeben. Ich habe ein Error.aspx
und ein erstellt PageNotFound.aspx
. Diese Seiten waren sehr einfach, aber sie hatten ein Stück Magie ...
<script type="text/C#" runat="server">
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
}
</script>
Dieser Block weist die Seite an, mit dem richtigen Statuscode bedient zu werden. Grob gesagt habe ich HttpStatusCode.NotFound
stattdessen auf der Seite PageNotFound.aspx verwendet . Ich habe meine web.config so geändert, dass sie so aussieht ...
<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
<error statusCode="404" redirect="~/PageNotFound.aspx" />
</customErrors>
Es hat alles perfekt funktioniert!
Zusammenfassung:
- Entfernen Sie die Linie:
filters.Add(new HandleErrorAttribute());
- Verwenden Sie die
Application_Error()
Methode, um Ausnahmen zu protokollieren
- Verwenden Sie customErrors mit einem ResponseRewrite, der auf ASPX-Seiten verweist
- Machen Sie die ASPX-Seiten für ihre eigenen Antwortstatuscodes verantwortlich
Es gibt ein paar Nachteile, die ich bei dieser Lösung bemerkt habe.
- Die ASPX-Seiten können kein Markup mit Razor-Vorlagen teilen. Ich musste das Standard-Markup für Kopf- und Fußzeilen unserer Website neu schreiben, um ein einheitliches Erscheinungsbild zu erzielen.
- Auf die * .aspx-Seiten kann direkt zugegriffen werden, indem ihre URLs eingegeben werden
Es gibt Workarounds für diese Probleme, aber ich war nicht besorgt genug, um zusätzliche Arbeit zu leisten.
Ich hoffe das hilft allen!