446 Stimmen

Wie kann ich 404 in ASP.NET MVC ordnungsgemäß behandeln?

Ich benutze RC2

Die Verwendung von URL-Routing:

routes.MapRoute(
    "Error",
     "{*url}",
     new { controller = "Errors", action = "NotFound" }  // 404s
);

Das obige scheint Anfragen wie diese zu bearbeiten (unter der Annahme der Standard-Routen, die beim initialen MVC-Projekt eingerichtet wurden): "/blah/blah/blah/blah"

Überschreiben von HandleUnknownAction() im Controller selbst:

// 404s - hier behandeln (falsche Aktion angefordert
protected override void HandleUnknownAction(string actionName) {
    ViewData["actionName"] = actionName;
    View("NotFound").ExecuteResult(this.ControllerContext);
}  

Die bisherigen Strategien behandeln jedoch keine Anfrage an einen schlechten/ unbekannten Controller. Wenn ich zum Beispiel keinen "/IDoNotExist" habe, und diesen anfordere, erhalte ich die generische 404-Seite vom Webserver und nicht meine 404, wenn ich Routing + Überschreibung verwende.

Meine Frage lautet also: Gibt es eine Möglichkeit, diese Art von Anfrage innerhalb des MVC-Frameworks selbst mit einer Route oder ähnlichem abzufangen?

ODER sollte ich einfach standardmäßig die Web.Config customErrors als meinen 404-Handler verwenden und all dies vergessen? Ich nehme an, wenn ich customErrors verwende, werde ich die generische 404-Seite außerhalb von /Views speichern müssen, aufgrund der Einschränkungen von Web.Config bezüglich des direkten Zugriffs.

3 Stimmen

Es handelt sich um einen 404-Fehler, ich würde mich einfach nicht darum kümmern. Lassen Sie ihn 404 anzeigen, da der Benutzer definitiv etwas falsch eingegeben hat. Oder wenn es sich um etwas handelt, das verschoben wurde, sollte Ihre Anwendung diese Anfrage entgegennehmen und eine permanente Weiterleitung durchführen. 404 gehört zum Webserver, nicht zur Anwendung. Sie können immer IIS-Seiten für Fehler anpassen.

0 Stimmen

Sie können sich auch diese Lösung ansehen blog.dantup.com/2009/04/…

0 Stimmen

ben.onfabrik.com/posts/aspnet-mvc-custom-error-pages hat auch einige gute Informationen.

279voto

Shay Jacoby Punkte 2882

Der Code stammt von http://blogs.microsoft.co.il/blogs/shay/archive/2009/03/06/real-world-error-hadnling-in-asp-net-mvc-rc2.aspx und funktioniert auch in ASP.net MVC 1.0

So handle ich http-Ausnahmen:

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

   ILogger logger = Container.Resolve();
   logger.Error(exception);

   Response.Clear();

   HttpException httpException = exception as HttpException;

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

   if (httpException == null)
   {
       routeData.Values.Add("action", "Index");
   }
   else //Es handelt sich um eine Http-Ausnahme, lass uns damit umgehen.
   {
       switch (httpException.GetHttpCode())
       {
          case 404:
              // Seite nicht gefunden.
              routeData.Values.Add("action", "HttpError404");
              break;
          case 500:
              // Serverfehler.
              routeData.Values.Add("action", "HttpError500");
              break;

           // Hier können Ansichten für andere Fehlercodes behandelt werden.
           // Ich wähle eine allgemeine Fehler-Vorlage
           default:
              routeData.Values.Add("action", "General");
              break;
      }
  }           

  // Ausnahme-Details an die Ziel-Fehleransicht übergeben.
  routeData.Values.Add("error", exception);

  // Fehler auf dem Server löschen.
  Server.ClearError();

  // Vermeiden, dass IIS7 dazwischenfunkt
  Response.TrySkipIisCustomErrors = true; 

  // Zielfehler-Controller aufrufen und die routeData übergeben.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData));
}

0 Stimmen

Ich möchte hinzufügen, dass es ziemlich einfach ist, Unittests für den obigen Code zu schreiben. Ich musste nur ein paar kleine Änderungen vornehmen. +1

0 Stimmen

Ich bin mir nicht sicher, warum du nach einer httpException suchst. Ist der Zweck dieses Handlers nicht, zum Beispiel eine NullReferenceException abzufangen und dann eine http-Ausnahme zu ERZEUGEN? Wann würde Server.GetLastError() tatsächlich eine HttpException sein, es sei denn, du hättest einen Http-Aufruf innerhalb deiner tatsächlichen Geschäftslogik gemacht. Ich habe dies aus meiner Implementierung entfernt, würde aber gerne wissen, ob es gerechtfertigt ist und ich etwas übersehen habe.

23 Stimmen

Update: Die Überprüfung eines HTTP 404 ist definitiv erforderlich, aber ich bin immer noch nicht ganz sicher, wann ein 500 auftreten würde. außerdem müssen Sie auch explizit Response.StatusCode = 404 oder 500 setzen, da Google sonst beginnt, diese Seiten zu indizieren, wenn Sie einen Statuscode 200 zurückgeben, was dieser Code derzeit tut.

258voto

Matt Kocaj Punkte 10936

Anforderungen für 404

Im Folgenden sind meine Anforderungen an eine 404-Lösung aufgeführt und ich zeige, wie ich sie implementiere:

  • Ich möchte übereinstimmende Routen mit schlechten Aktionen behandeln
  • Ich möchte angepasste Routen mit schlechten Controllern behandeln
  • Ich möchte nicht übereinstimmende Routen (willkürliche URLs, die meine App nicht verstehen kann) behandeln - ich möchte nicht, dass diese bis zu den Global.asax oder IIS blubbern, weil dann Ich kann nicht richtig zu meiner MVC-App zurückkehren
  • Ich möchte eine Möglichkeit, in der gleichen Weise wie oben, benutzerdefinierte 404s zu behandeln - wie wenn eine ID für ein Objekt, das nicht existiert (vielleicht gelöscht) übermittelt wird
  • Ich möchte alle meine 404s eine MVC-Ansicht (nicht eine statische Seite) zurückgeben, auf die ich mehr Daten später bei Bedarf pumpen kann ( 404 gute Entwürfe ) und sie doit den HTTP-Statuscode 404 zurückgeben

Lösung

Ich denke, Sie sollten sparen Application_Error in der Global.asax für größere Dinge, wie unbehandelte Ausnahmen und Protokollierung (wie Shay Jacoby's Antwort zeigt), nicht aber die 404-Behandlung. Deshalb ist mein Vorschlag, die 404-Sachen aus der Global.asax-Datei herauszuhalten.

Schritt 1: Ein gemeinsamer Ort für die 404-Fehler-Logik

Dies ist eine gute Idee für die Wartbarkeit. Verwenden Sie eine ErrorController damit künftige Verbesserungen an Ihrem gut gestaltete 404-Seite leicht anpassen können. Auch, Stellen Sie sicher, dass Ihre Antwort den 404-Code enthält. !

public class ErrorController : MyController
{
    #region Http404

    public ActionResult Http404(string url)
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        var model = new NotFoundViewModel();
        // If the url is relative ('NotFound' route) then replace with Requested path
        model.RequestedUrl = Request.Url.OriginalString.Contains(url) & Request.Url.OriginalString != url ?
            Request.Url.OriginalString : url;
        // Dont get the user stuck in a 'retry loop' by
        // allowing the Referrer to be the same as the Request
        model.ReferrerUrl = Request.UrlReferrer != null &&
            Request.UrlReferrer.OriginalString != model.RequestedUrl ?
            Request.UrlReferrer.OriginalString : null;

        // TODO: insert ILogger here

        return View("NotFound", model);
    }
    public class NotFoundViewModel
    {
        public string RequestedUrl { get; set; }
        public string ReferrerUrl { get; set; }
    }

    #endregion
}

Schritt 2: Verwenden Sie eine Basis-Controller-Klasse, damit Sie Ihre benutzerdefinierte 404-Aktion einfach aufrufen und verdrahten können HandleUnknownAction

404er in ASP.NET MVC müssen an mehreren Stellen abgefangen werden. Die erste ist HandleUnknownAction .

El InvokeHttp404 Methode schafft einen gemeinsamen Ort für die Weiterleitung an die ErrorController und unser neues Http404 Aktion. Denken Sie an DRY !

public abstract class MyController : Controller
{
    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        // If controller is ErrorController dont 'nest' exceptions
        if (this.GetType() != typeof(ErrorController))
            this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<ErrorController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Error");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

    #endregion
}

Schritt 3: Verwenden Sie Dependency Injection in Ihrem Controller Factory und Draht bis 404 HttpExceptions

Etwa so (es muss nicht StructureMap sein):

MVC1.0 Beispiel:

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(RequestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

MVC2.0 Beispiel:

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == 404)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(requestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }

Ich denke, es ist besser, Fehler dort zu erkennen, wo sie entstehen. Deshalb ziehe ich die obige Lösung der Application_Error Handler.

Dies ist der zweite Ort, an dem 404er abgefangen werden.

Schritt 4: Fügen Sie eine NotFound-Route zu Global.asax für Urls hinzu, die nicht in Ihre Anwendung geparst werden können

Diese Route sollte auf unsere Http404 Aktion. Beachten Sie die url param wird eine relative Url sein, weil die Routing-Engine den Domain-Teil hier entfernt? Deshalb haben wir die ganze bedingte Url-Logik in Schritt 1.

        routes.MapRoute("NotFound", "{*url}", 
            new { controller = "Error", action = "Http404" });

Dies ist der dritte und letzte Ort, um 404er in einer MVC-Anwendung abzufangen, die Sie nicht selbst aufrufen. Wenn Sie hier keine unpassenden Routen abfangen, wird MVC das Problem an ASP.NET (Global.asax) weitergeben, und das wollen Sie in dieser Situation nicht wirklich.

Schritt 5: Rufen Sie schließlich 404s auf, wenn Ihre App etwas nicht finden kann

Wenn z. B. eine fehlerhafte ID an meinen Loans-Controller übermittelt wird (abgeleitet von MyController ):

    //
    // GET: /Detail/ID

    public ActionResult Detail(int ID)
    {
        Loan loan = this._svc.GetLoans().WithID(ID);
        if (loan == null)
            return this.InvokeHttp404(HttpContext);
        else
            return View(loan);
    }

Es wäre schön, wenn all dies an weniger Stellen mit weniger Code verbunden werden könnte, aber ich denke, diese Lösung ist besser wartbar, besser testbar und ziemlich pragmatisch.

Vielen Dank für das bisherige Feedback. Ich würde gerne mehr bekommen.

HINWEIS: Diese Frage wurde gegenüber meiner ursprünglichen Antwort erheblich geändert, aber der Zweck/die Anforderungen sind die gleichen - deshalb habe ich keine neue Antwort hinzugefügt.

0 Stimmen

Dude - ich mag das wirklich wirklich gerne :) Früher habe ich Http404Exceptions geworfen usw. und das in einem OnError-Attributtyp behandelt .. aber das ist auch verdammt gut :)

0 Stimmen

@cottsak Kumpel, mit deinem StructureMap IoC-Code .. wann (oder wie) kann eine HttpException ausgelöst werden? Ein einfaches Beispiel, bitte? Und zweitens, warum ruft dein Code in Schritt #5 invoke404 auf und gibt dann EmptyResult zurück??

0 Stimmen

@Krome: #1- "Der Controller für den Pfad '/dfsdf' konnte nicht gefunden werden oder implementiert nicht IController." ist die .Message bei Aufruf des Pfads '/dfsdf' - ich vermute, wenn eine Route nicht übereinstimmt, wirft MVC eine HttpException wie diese. #2- Schritt 5 ist vielleicht kein ideales Anwendungsbeispiel, aber für mich scheint es vorerst in Ordnung zu sein. Ich muss den EmptyResult als Teil der Aktion zurückgeben. Die Tatsache, dass es "leer" ist, macht keinen Unterschied, da ich im InvokeHttp404 Methode erneut umleite. Hilfe?

241voto

Pavel Chuchuva Punkte 21957

ASP.NET MVC unterstützt benutzerdefinierte 404-Seiten nicht sehr gut. Benutzerdefinierte Controller-Fabrik, Catch-All-Route, Basisklassen-Controller mit HandleUnknownAction - ätzend!

IIS-Benutzerdefinierte Fehlerseiten sind bisher eine bessere Alternative:

web.config

ErrorController

public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View();
    }
}

Beispielprojekt

40 Stimmen

DIES SOLLTE DIE AKZEPTIERTE ANTWORT GEWESEN SEIN!!! Funktioniert hervorragend auf ASP.NET MVC 3 mit IIS Express.

7 Stimmen

Wenn Sie IIS7+ verwenden, ist dies definitiv der richtige Weg. +1!

0 Stimmen

@jayrdub Ich kann das Problem mit der 302-Umleitung vor der 404-Seite nicht reproduzieren. Ich habe ein Testprojekt erstellt und es funktioniert wie erwartet - die 404-Seite gibt den 404-Code zurück. Siehe dl.dropbox.com/u/2019363/Test404.zip

154voto

Pure.Krome Punkte 81543

Schnelle Antwort / TL;DR

Bildbeschreibung hier eingeben

Für die faulen Leute da draußen:

Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0

Dann entfernen Sie diese Zeile aus global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

Und dies gilt nur für IIS7+ und IIS Express.

Wenn Sie Cassini verwenden .. nun .. ähm .. peinlich ... peinlich


Lange, ausführliche Antwort

Ich weiß, dass dies beantwortet wurde. Aber die Antwort ist WIRKLICH EINFACH (Applaus für David Fowler und Damian Edwards für die wirklich gute Antwort).

Es ist nicht erforderlich, irgendetwas anzupassen.

Für ASP.NET MVC3 sind alle benötigten Teile vorhanden.

Schritt 1 -> Aktualisieren Sie Ihre web.config an ZWEI Stellen.

und

...

...

Beachten Sie jetzt genau die ROUTEN, die ich gewählt habe. Sie können alles verwenden, aber meine Routen sind

  • /NotFound <- für eine 404 Seite nicht gefunden Fehlerseite.
  • /ServerError <- für jeden anderen Fehler, einschließlich Fehler, die in meinem Code auftreten. dies ist ein 500 Interner Serverfehler

Sehen Sie, wie der erste Abschnitt in nur einen benutzerdefinierten Eintrag hat? Den statusCode="404" Eintrag? Ich habe nur einen Statuscode aufgelistet, weil alle anderen Fehler, einschließlich des 500 Serverfehlers (d.h. diese lästigen Fehler, die auftreten, wenn Ihr Code einen Fehler hat und die Anfrage des Benutzers abstürzt) .. alle anderen Fehler werden durch die Einstellung defaultRedirect="/ServerError" behandelt .. was besagt, wenn es sich nicht um eine 404 Seite nicht gefunden handelt, gehen Sie bitte zur Route /ServerError.

Ok. das wäre erledigt.. jetzt zu meinen Routen, die in global.asax

Schritt 2 - Erstellen der Routen in Global.asax

Hier ist mein vollständiger Routenabschnitt..

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});

    routes.MapRoute(
        "Fehler - 404",
        "NotFound",
        new { controller = "Error", action = "NotFound" }
        );

    routes.MapRoute(
        "Fehler - 500",
        "ServerError",
        new { controller = "Error", action = "ServerError"}
        );

    routes.MapRoute(
        "Standard", // Routenname
        "{controller}/{action}/{id}", // URL mit Parametern
        new {controller = "Home", action = "Index", id = UrlParameter.Optional}
        );
}

Das listet zwei Auslassrouten -> axd und favicons (ooo! Bonus-Auslassroute für euch!) Dann (und die Reihenfolge ist HIER WICHTIG), habe ich meine beiden expliziten Fehlerbehandlungsrouten .. gefolgt von allen anderen Routen. In diesem Fall die Standardroute. Natürlich habe ich mehr, aber das ist speziell für meine Website. Stellen Sie einfach sicher, dass die Fehlerrouten oben auf der Liste stehen. Die Reihenfolge ist ausschlaggebend.

Zum Schluss, während wir in unserer global.asax Datei sind, registrieren wir NICHT global das HandleError-Attribut. Nein, nein, nein Herr. Nadda. Nope. Nien. Negativ. Neiiiiiin...

Entfernen Sie diese Zeile aus global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

Schritt 3 - Erstellen des Controllers mit den Aktionsmethoden

Nun .. fügen wir einen Controller mit zwei Aktionsmethoden hinzu ...

public class ErrorController : Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ActionResult ServerError()
    {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        // Todo: Übergeben Sie die Ausnahme dem ViewModel, das Sie erstellen können.
        //       Das ist eine Übung, liebe Leser, für -dich-.
        //       Falls Sie es dem View übergeben möchten, wenn Sie Admin sind, usw.
        // if (User.IsAdmin) // <-- Das habe ich mir gerade ausgedacht :) Sie verstehen die Idee..
        // {
        //     var exception = Server.GetLastError();
        //     // etc..
        // }

        return View();
    }

    // Psst .. geheime Testmethode .. ooOoOoOooOOoooohhhhhh
    public ActionResult ThrowError()
    {
        throw new NotImplementedException("Pew ^ Pew");
    }
}

Ok, lasst uns das überprüfen. Zunächst einmal gibt es hier KEIN [HandleError] Attribut. Warum? Weil das integrierte ASP.NET-Framework bereits Fehler behandelt UND wir alle Schritte spezifiziert haben, die wir benötigen, um einen Fehler zu behandeln :) Es steckt in dieser Methode!

Dann habe ich die beiden Aktionsmethoden. Nichts Schwieriges dabei. Wenn Sie irgendwelche Ausnahmeinformationen anzeigen möchten, können Sie Server.GetLastError() verwenden, um diese Informationen zu erhalten.

Bonus WTF: Ja, ich habe eine dritte Aktionsmethode erstellt, um die Fehlerbehandlung zu testen.

Schritt 4 - Erstellen der Ansichten

Und schließlich zwei Ansichten erstellen. Legen Sie sie an die normale Stelle für Ansichten dieses Controllers.

Bildbeschreibung hier eingeben

Bonuskommentare

  • Sie benötigen keine Application_Error(object sender, EventArgs e)
  • Die obigen Schritte funktionieren alle zu 100% perfekt mit Elmah. Elmah fraking wroxs!

Und das, meine Freunde, sollte es sein.

Herzlichen Glückwunsch, dass Sie so viel gelesen haben, und als Belohnung haben Sie einen Einhorn!

Bildbeschreibung hier eingeben

0 Stimmen

Also habe ich versucht, das umzusetzen, aber ein paar Probleme... erstens brauchen Sie ein ~ vor dem Pfad in weeb.config, sonst funktioniert es nicht für virtuelle Verzeichnisse. 2-Wenn benutzerdefinierte IIS-Fehler auftreten und die Ansicht ein Layout verwendet, wird überhaupt nichts gerendert, nur eine weiße Seite. Ich habe das gelöst, indem ich diese Zeile in den Controller eingefügt habe "Response.TrySkipIisCustomErrors = true;". Es funktioniert jedoch immer noch nicht, wenn Sie eine URL aufrufen, die eine Datei ist, aber 404... wie mysite/whatever/fake.html eine weiße Seite zeigt.

3 Stimmen

-1, Entschuldigung, für mich ist jede Lösung, die die URL für 404 ändert, falsch. Und mit der Web-Konfiguration gibt es keinen Weg in MVC, um dies zu handhaben, ohne die URL zu ändern, oder Sie müssen statische HTML-Dateien oder aspx (ja, einfache alte aspx-Dateien) erstellen, um es zu ermöglichen. Deine Lösung ist in Ordnung, wenn du möchtest, dass ?aspxerrorpath=/er/not/found in den URLs erscheint.

8 Stimmen

Dies mag wirklich komisch klingen - aber meine Antwort wurde vor langer Zeit gegeben und ich stimme deinem @Gutek zu, ich mag es nicht mehr, auf eine Fehlerseite umzuleiten anymore. Früher habe ich das gemacht (siehe meine Antwort :P). Wenn der Fehler auf / irgendwelche / Ressource auftrat .. sollte DAS die 404 oder 500 zurückgeben, usw. MASSIVE SEO-Auswirkungen sonst. Ahh .. wie sich die Zeiten ändern :)

90voto

Marco Punkte 5040

Ich habe VIEL darüber recherchiert, wie man 404s in MVC (speziell MVC3) ordnungsgemäß verwalten kann, und meiner Meinung nach ist dies die beste Lösung, die ich gefunden habe:

In der global.asax:

public class MvcApplication : HttpApplication
{
    protected void Application_EndRequest()
    {
        if (Context.Response.StatusCode == 404)
        {
            Response.Clear();

            var rd = new RouteData();
            rd.DataTokens["area"] = "AreaName"; // Falls der Controller in einem anderen Bereich ist
            rd.Values["controller"] = "Errors";
            rd.Values["action"] = "NotFound";

            IController c = new ErrorsController();
            c.Execute(new RequestContext(new HttpContextWrapper(Context), rd));
        }
    }
}

ErrorsController:

public sealed class ErrorsController : Controller
{
    public ActionResult NotFound()
    {
        ActionResult result;

        object model = Request.Url.PathAndQuery;

        if (!Request.IsAjaxRequest())
            result = View(model);
        else
            result = PartialView("_NotFound", model);

        return result;
    }
}

(Optional)

Erklärung:

Soweit ich weiß, gibt es 6 verschiedene Fälle, in denen ein ASP.NET MVC3-App 404s generieren kann.

(Automatisch generiert durch das ASP.NET Framework:)

(1) Eine URL findet keine Übereinstimmung in der Routentabelle.

(Automatisch generiert durch das ASP.NET MVC Framework:)

(2) Eine URL findet eine Übereinstimmung in der Routentabelle, gibt aber einen nicht existierenden Controller an.

(3) Eine URL findet eine Übereinstimmung in der Routentabelle, gibt aber eine nicht vorhandene Aktion an.

(Manuell generiert:)

(4) Eine Aktion liefert ein HttpNotFoundResult zurück, indem die Methode HttpNotFound() verwendet wird.

(5) Eine Aktion wirft eine HttpException mit dem Statuscode 404.

(6) Eine Aktion ändert manuell die Response.StatusCode-Eigenschaft in 404.

Normalerweise möchten Sie 3 Ziele erreichen:

(1) Dem Benutzer eine benutzerdefinierte 404-Fehlerseite anzeigen.

(2) Den HTTP-Statuscode 404 auf der Clientantwort beibehalten (besonders wichtig für SEO).

(3) Die Antwort direkt senden, ohne eine 302-Weiterleitung einzubeziehen.

Es gibt verschiedene Möglichkeiten, dies zu versuchen:

(1)

Probleme mit dieser Lösung:

  1. Entspricht nicht Ziel (1) in den Fällen (1), (4), (6).
  2. Entspricht nicht automatisch Ziel (2). Es muss manuell programmiert werden.
  3. Entspricht nicht Ziel (3).

(2)

Probleme mit dieser Lösung:

  1. Funktioniert nur auf IIS 7+.
  2. Entspricht nicht Ziel (1) in den Fällen (2), (3), (5).
  3. Entspricht nicht automatisch Ziel (2). Es muss manuell programmiert werden.

(3)

Probleme mit dieser Lösung:

  1. Funktioniert nur auf IIS 7+.
  2. Entspricht nicht automatisch Ziel (2). Es muss manuell programmiert werden.
  3. Es verbirgt http-Ausnahmen auf Anwendungsebene. Z.B. kann die customErrors-Sektion, System.Web.Mvc.HandleErrorAttribute usw. nicht verwendet werden. Es können nur generische Fehlerseiten angezeigt werden.

(4)

und

Probleme mit dieser Lösung:

  1. Funktioniert nur auf IIS 7+.
  2. Entspricht nicht automatisch Ziel (2). Es muss manuell programmiert werden.
  3. Entspricht nicht Ziel (3) in den Fällen (2), (3), (5).

Menschen, die damit zu kämpfen hatten, haben sogar versucht, ihre eigenen Bibliotheken zu erstellen (siehe http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html). Aber die vorherige Lösung scheint alle Fälle abzudecken, ohne die Komplexität der Verwendung einer externen Bibliothek.

0 Stimmen

Tolle Antwort. Verdient viele weitere Upvotes. Warum funktioniert/dein global.asax Code nicht in Application_Error?

7 Stimmen

Vielen Dank! Dies kann nicht unter Application_Error ausgeführt werden, da explizite 404er-Fehler, die von einem Controller geworfen werden, auf ASP.NET nicht als Fehler betrachtet werden. Wenn Sie ein HttpNotFound() von einem Controller zurückgeben, wird das Application_Error-Ereignis niemals ausgelöst.

1 Stimmen

Ich glaube, du hast public ActionResult NotFound() {} in deinem ErrorsController vergessen. Kannst du auch erklären, wie dein _NotFound Teil für AJAX-Anfragen aussehen würde?

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X