Routing für benutzerdefinierte ASP.NET MVC 404-Fehlerseite

116

Ich versuche, eine benutzerdefinierte HTTP 404-Fehlerseite zu erstellen, wenn jemand eine URL eingibt, die keine gültige Aktion oder keinen gültigen Controller in ASP.NET MVC aufruft, anstatt den generischen ASP.NET-Fehler "Ressource nicht gefunden" anzuzeigen.

Ich möchte die web.config nicht verwenden, um damit umzugehen.

Gibt es irgendeine Art von Routing-Magie, mit der ich ungültige URLs abfangen kann?

Update: Ich habe die Antwort ausprobiert, erhalte jedoch immer noch die hässliche Meldung "Ressource nicht gefunden".

Noch ein Update: Ok, anscheinend hat sich in RC1 etwas geändert. Ich habe sogar versucht, 404 speziell auf einer zu fangen, HttpExceptionund es gibt mir immer noch nur die Seite "Ressource nicht gefunden".

Ich habe sogar die Ressourcenfunktion von MvcContrib verwendet und nichts - das gleiche Problem. Irgendwelche Ideen?

dswatik
quelle
@Peter Das ist die Lösung, die ich hinzugefügt habe, zusammen mit dem Überschreiben der HandleUnknownAction, um eine Seite nicht gefundene Ansicht anzuzeigen, wenn eine Aktion nicht vorhanden ist, und dann der eingebaute benutzerdefinierte ASP.net-Fehlerbehandler, um alles andere zu verarbeiten, was Benutzer eingeben können .
dswatik
@pete Dies funktioniert auch stackoverflow.com/questions/619895/…
dswatik
8
Ich hasse es, wenn andere Benutzer anmaßend sind und Dinge sagen wie: "Warum sollten Sie das tun? Tun Sie dies einfach ...". Aber ich würde vorschlagen, wenn Sie nichts daran hindert, den web.config-Ansatz und ihn zu verwenden erfüllt Ihre Bedürfnisse, es ist ein Standard und eleganter Ansatz. Jedes Feedback zu diesem Ansatz ist willkommen, da es durchaus Probleme geben kann, von denen ich nichts weiß.
Sean

Antworten:

10

Fügen Sie am Ende der Routentabelle einfach catch all route hinzu und zeigen Sie die gewünschte Seite an.

Siehe: Wie kann ich eine Route abfangen, um alle Abfragen für ASP.NET MVC zu verarbeiten?

Alex Reitbort
quelle
Ich habe dies versucht, aber ich bekomme immer noch die hässliche ASP.NET-Standardnachricht "Ressource nicht gefunden".
dswatik
3
Ich finde weder in dieser Antwort noch auf dem angegebenen Link eine endgültige (und flexible !!) Lösung für dieses Problem.
Peter
4
Ich auch nicht ... das scheint eine Art hackige Antwort zu sein. Ich suche eher nach einer Möglichkeit, benutzerdefinierte Fehler so zu gestalten, wie sie es in WebForms tun. Irgendwelche Ideen?
JC Grubbs
1
Dies funktioniert nicht und ist grundsätzlich schlecht. Funktioniert nicht, da keine schlechten URLs abgefangen werden, die mit einem der früheren Routenmuster übereinstimmen. Bad grundsätzlich , weil es konvertiert , was sollte nicht ein Fehler ein Fehler sein. Das Umleiten auf eine Seite mit dem Namen "Fehler" unterscheidet sich vom Umleiten auf eine Fehlerseite. Sie möchten es als Fehler behalten, den Fehler protokollieren und dann als Fehler behandeln. Fehler sind wertvolle Informationen.
Matthew
105

Ich habe 3 Stunden lang versucht, benutzerdefinierte Fehler auf dem Produktionsserver zu aktivieren. Anscheinend habe ich eine endgültige Lösung gefunden, wie dies in ASP.NET MVC ohne Routen durchgeführt werden kann.

Um benutzerdefinierte Fehler in der ASP.NET MVC-Anwendung zu aktivieren, benötigen wir (IIS 7+):

  1. Konfigurieren Sie benutzerdefinierte Seiten in der Webkonfiguration unter system.webAbschnitt:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>

    RemoteOnlybedeutet, dass im lokalen Netzwerk echte Fehler auftreten (sehr nützlich während der Entwicklung). Wir können die Fehlerseite auch für jeden Fehlercode neu schreiben.

  2. Stellen Sie den magischen Antwortparameter und den Antwortstatuscode ein (im Fehlerbehandlungsmodul oder im Fehlerbehandlungsattribut).

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
  3. Stellen Sie eine andere magische Einstellung in der Webkonfiguration unter system.webServerAbschnitt ein:

    <httpErrors errorMode="Detailed" />

Dies war die letzte Sache, die ich gefunden habe, und danach kann ich benutzerdefinierte Fehler auf dem Produktionsserver sehen.

Andrew Orsich
quelle
8
Dies ist immer noch keine ideale Lösung. Sie erhalten keine richtigen HTTP-Antwortcodes. Verwenden von customErrorsErgebnissen in einer 302-Umleitung, nur um Ihre Fehlerseite zu laden.
Justin Helgerson
@ Ek0nomik Ich habe noch nie ideale Lösungen gesehen :)
Andrew Orsich
2
@JustinHelgerson Ich habe für jeden Statuscode einen ErrorController eingerichtet und die Antwortcodes in diesen Aktionen festgelegt. Außerdem werden die Antwortcodes in Ordnung gesetzt. Ich habe mit Fiddler getestet und 404-Statuscodes antworten mit einem 404 und Seiten mit 500 Fehlern antworten mit einem 500. Und In beiden Fällen werden meine benutzerdefinierten Fehleransichten angezeigt
Shane Neuville
Mein Teamkollege hat gerade die Fehleransicht im freigegebenen Ordner gelöscht , um einen Laufzeitfehler mit 500 Statuscode zu verursachen und zur benutzerdefinierten Fehlerseite umzuleiten, wie hier und hier erwähnt . Hoffnung hilft jemandem.
Shaijut
41

Ich habe meine Fehlerbehandlung zum Laufen gebracht, indem ich einen ErrorController erstellt habe, der die Ansichten in diesem Artikel zurückgibt. Ich musste auch die "Catch All" zur Route in global.asax hinzufügen.

Ich kann nicht sehen, wie es zu einer dieser Fehlerseiten kommt, wenn es nicht in der Web.config ist ..? Meine Web.config musste angeben:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

und dann habe ich noch hinzugefügt:

error statusCode="404" redirect="~/Error/NotFound"
Jack Smit
quelle
2
Danke - das hat mir 2 Jahre später geholfen! Was tun Sie, wenn Sie nur einen benutzerdefinierten Fehler für 404 möchten, sonst nichts?
Shaul Behr
1
@Shaul ein weiteres Jahr später ... setze nicht die defaultRedirect, sondern schließe das Attribut insgesamt aus.
NJE
27

Quelle

NotFoundMVC - Bietet eine benutzerfreundliche 404-Seite, wenn in Ihrer ASP.NET MVC3-Anwendung kein Controller, keine Aktion oder Route gefunden wird. Anstelle der Standard-ASP.NET-Fehlerseite wird eine Ansicht mit dem Namen NotFound gerendert.

Sie können dieses Plugin über Nuget hinzufügen, indem Sie Folgendes installieren: Install-Package NotFoundMvc

NotFoundMvc installiert sich automatisch beim Start der Webanwendung. Es behandelt die verschiedenen Arten, wie eine 404 HttpException normalerweise von ASP.NET MVC ausgelöst wird. Dies beinhaltet einen fehlenden Controller, eine fehlende Aktion und eine fehlende Route.

Schritt für Schritt Installationsanleitung:

1 - Klicken Sie mit der rechten Maustaste auf Ihr Projekt und wählen Sie Nuget-Pakete verwalten ...

2 - Suchen nach NotFoundMvc und installieren Sie es. Geben Sie hier die Bildbeschreibung ein

3 - Nach Abschluss der Installation werden Ihrem Projekt zwei Dateien hinzugefügt. Wie in den folgenden Screenshots gezeigt.

Geben Sie hier die Bildbeschreibung ein

4 - Öffnen Sie die neu hinzugefügte NotFound.cshtml unter Ansichten / Freigegeben und ändern Sie sie nach Belieben. Führen Sie nun die Anwendung aus und geben Sie eine falsche URL ein. Sie werden dann mit einer benutzerfreundlichen 404-Seite begrüßt.

Geben Sie hier die Bildbeschreibung ein

Nicht mehr, werden Benutzer Fehlermeldungen wie erhalten Server Error in '/' Application. The resource cannot be found.

Hoffe das hilft :)

PS: Ein großes Lob an Andrew Davey für das tolle Plugin.

Yasser Shaikh
quelle
@niico Beim Betrachten des Quellcodes scheint der Antwortcode auf 404 gesetzt zu sein, also ja.
Will Dean
20

Versuchen Sie dies in web.config, um IIS-Fehlerseiten zu ersetzen. Dies ist die beste Lösung, die ich denke, und sie sendet auch den richtigen Statuscode aus.

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

Weitere Informationen von Tipila - Benutzerdefinierte Fehlerseiten verwenden ASP.NET MVC

Amila
quelle
1
+1. Dies ist das einzige, was für mich auf MVC5 mit mehreren Bereichen konsistent zu funktionieren schien.
Hawkke
Dies ist die einfachste Lösung. Sie können jedoch keine Rasierersyntax auf Ihrer Fehlerseite verwenden.
Highace
15

Diese Lösung benötigt keine Änderungen an der Datei web.config oder Catch-All-Routen.

Erstellen Sie zunächst einen Controller wie diesen.

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        ViewBag.Title = "Regular Error";
        return View();
    }

    public ActionResult NotFound404()
    {
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    }
}

Erstellen Sie dann die Ansicht unter "Ansichten / Fehler / Index.cshtml" als;

 @{
      Layout = "~/Views/Shared/_Layout.cshtml";
  }                     
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

Fügen Sie dann wie folgt Folgendes in die globale Asax-Datei ein:

protected void Application_Error(object sender, EventArgs e)
{
        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        {
            routeData.Values["action"] = "Index";
        }
        else
        {
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
        } 
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();
}

Wenn Sie danach immer noch die benutzerdefinierte IIS-Fehlerseite erhalten, stellen Sie sicher, dass die folgenden Abschnitte in der Webkonfigurationsdatei auskommentiert (oder leer) sind:

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>
Sujeewa
quelle
Ich denke nicht, dass dieser Ansatz in allen Fällen funktioniert, da ein 404 häufig vom Webserver abgefangen und daher nie auf Anwendungsebene behandelt wird.
Chris Halcrow
Ich möchte hinzufügen, dass ich bei diesem Ansatz empfehlen würde Response.End();, am Ende Ihres Application_Error-Handlers ein a hinzuzufügen . Ohne dies wird nur das erste Auftreten eines Fehlers für eine bestimmte Sitzung ausgelöst. Dies ist ein Problem, wenn Sie beispielsweise eine benutzerdefinierte Fehlerprotokollierung im Application_Error-Handler haben.
Keith
6

Wenn Sie in MVC 4 arbeiten, können Sie sich diese Lösung ansehen , sie hat bei mir funktioniert.

Fügen Sie die folgende Application_Error-Methode zu my hinzu Global.asax:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    {
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    }
    else
    {
        routeData.Values.Add("statusCode", 500);
    }

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

Der Controller selbst ist wirklich einfach:

public class ErrorController : Controller
{
    public ActionResult Index(int statusCode, Exception exception)
    {
        Response.StatusCode = statusCode;
        return View();
    }
}

Überprüfen Sie den vollständigen Quellcode von Mvc4CustomErrorPage bei GitHub .

Duc Hoang
quelle
0

Ich hatte das gleiche Problem. Sie müssen lediglich das Attribut customErrors in der Datei web.config in Ihrem Ordner Views hinzufügen, sondern es in der Datei web.config in Ihrem Projektstammordner hinzufügen

Rauche es
quelle
0

Hier ist eine echte Antwort, die es ermöglicht, die Fehlerseite an einem Ort vollständig anzupassen. Sie müssen web.config nicht ändern oder separaten Code erstellen.

Funktioniert auch in MVC 5.

Fügen Sie diesen Code zur Steuerung hinzu:

        if (bad) {
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        }

Basierend auf http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages

Andrus
quelle
0

Ich werde über einige spezielle Fälle sprechen,

Wenn Sie die 'PageNotFound-Methode' in HomeController wie unten verwenden

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

das würde nicht funktionieren. Sie müssen jedoch die Routentags wie unten löschen.

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

Und wenn Sie es als Methodenname in web.config ändern , funktioniert es. Vergessen Sie jedoch nicht, Code wie unten in web.config auszuführen

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>
Furkan ozturk
quelle