12 Stimmen

ASP.NET MVC - Wie man eine 404-Seite wirft, ähnlich der auf StackOverflow

Ich habe derzeit eine BaseController-Klasse, die von System.Web.Mvc.Controller erbt. In dieser Klasse habe ich das HandleError-Attribut, das Benutzer auf die Seite "500 - Oops, wir haben Mist gebaut" umleitet. Dies funktioniert derzeit wie erwartet.

DAS FUNKTIONIERT

 _
Public Class BaseController : Inherits System.Web.Mvc.Controller

''# etwas tun
End Class

Auch meine 404-Seiten funktionieren auf Basis von Per-ActionResult, was auch wie erwartet funktioniert.

DAS FUNKTIONIERT

    Function Details(ByVal id As Integer) As ActionResult
        Dim user As Domain.User = UserService.GetUserByID(id)

        If Not user Is Nothing Then
            Dim userviewmodel As Domain.UserViewModel = New Domain.UserViewModel(user)
            Return View(userviewmodel)
        Else
            ''# Aufgrund von RESTful-URLs möchten einige Leute "herumstöbern",
            ''# indem sie Nummern in die Adresse eingeben. Wir müssen sie
            ''# sanft auf eine nicht gefundene Seite umleiten, wenn der Benutzer nicht
            ''# existiert.
            Response.StatusCode = CInt(HttpStatusCode.NotFound)
            Return View("NotFound")
        End If

    End Function

Auch dies funktioniert großartig. Wenn ein Benutzer z.B. etwas wie http://example.com/user/999 eingibt (wobei die Benutzer-ID 999 nicht existiert), sehen sie die entsprechende 404-Seite, und dennoch ändert sich die URL nicht (sie werden nicht auf eine Fehlerseite umgeleitet).

ICH KANN DIESE IDEE NICHT ZUM LAUFEN BRINGEN

Hier habe ich ein Problem. Wenn ein Benutzer z.B. http://example.com/asdf- eingibt, werden sie zur generischen 404-Seite weitergeleitet. Was ich tun möchte, ist die URL intakt zu lassen (d.h. keine Umleitung auf eine andere Seite), sondern einfach die "NotFound"-Ansicht anzuzeigen und das HttpStatusCode.NotFound an den Client zu senden.

Zum Beispiel besuchen Sie einfach https://stackoverflow.com/asdf, wo Sie die benutzerdefinierte 404-Seite sehen und die URL intakt lassen.

Offensichtlich fehlt mir etwas, aber ich kann es nicht herausfinden. Da "asdf" nicht tatsächlich auf einen Controller verweist, wird meine Basisklassen-Controller-Klasse nicht aktiviert, sodass ich es nicht im "HandleError"-Filter dort tun kann.

Vielen Dank im Voraus für die Hilfe.

Hinweis: Ich möchte den Benutzer auf keinen Fall auf eine 404-Seite umleiten. Ich möchte, dass sie unter der aktuellen URL bleiben und dass MVC die 404-ANSICHT an den Benutzer sendet.

Bearbeiten:

Ich habe auch Folgendes erfolglos versucht.

Shared Sub RegisterRoutes(ByVal routes As RouteCollection)
    routes.RouteExistingFiles = False
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
    routes.IgnoreRoute("Assets/{*pathInfo}")
    routes.IgnoreRoute("{*robotstxt}", New With {.robotstxt = "(.*/)?robots.txt(/.*)?"})

    routes.AddCombresRoute("Combres")

    ''# MapRoute ermöglicht eine dynamische UserDetails-ID
    routes.MapRouteLowercase("UserProfile", _
        "Users/{id}/{slug}", _
        New With {.controller = "Users", .action = "Details", .slug = UrlParameter.Optional}, _
        New With {.id = "\d+"} _
    )

    ''# Standard Catch All Gültige Routen
    routes.MapRouteLowercase( _
        "Standard", _
        "{controller}/{action}/{id}/{slug}", _
        New With {.controller = "Events", .action = "Index", .id = UrlParameter.Optional, .slug = UrlParameter.Optional} _
    )

    ''# Fangen Sie alle ungültigen (Nicht gefundenen) Routen ab
    routes.MapRoute( _
        "NotFound", _
        "{*url}", _
        New With {.controller = "Error", .action = "NotFound"})

End Sub

Meine "NotFound"-Route tut nichts.

9voto

Chase Florell Punkte 44519

Ich habe meine Antwort in meiner anderen SO-Frage gefunden. Vielen Dank Anh-Kiet Ngo für die Lösung.

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

    // Ein guter Ort für jegliches Fehlerprotokollierung, ansonsten, mach es im Error-Controller.

    Response.Clear();
    HttpException httpException = exception as HttpException;
    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "YourErrorController");

    if (httpException != null)
    {
        if (httpException.GetHttpCode() == 404)
        {
            routeData.Values.Add("action", "YourErrorAction");

            // Wir können die Exception auch an die Action übergeben, so etwas wie
            // routeData.Values.Add("error", exception);

            // Den Fehler löschen, sonst erhalten wir immer die Standardfehlerseite.
            Server.ClearError();

            // Den Controller mit der Route aufrufen
            IController errorController = new ApplicationName.Controllers.YourErrorController();
            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        }
    }
}

3voto

mathieu Punkte 30503

Sie könnten versuchen:

http://msdn.microsoft.com/en-us/library/system.web.configuration.customerrorssection.redirectmode.aspx

Wenn die RedirectMode-Eigenschaft auf ResponseRewrite gesetzt ist, wird der Benutzer zur Fehlerseite weitergeleitet und die ursprüngliche URL im Browser wird nicht geändert.

1voto

Keith Punkte 141163

Routes sind Musterübereinstimmungen. Ihre nicht gefundene Route funktioniert nicht, weil das Muster Ihrer falschen URL mit einer früheren Route übereinstimmt.

Also:

''# Standard für alle gültigen Routen
routes.MapRouteLowercase( _
    "Standard", _
    "{controller}/{action}/{id}/{slug}", _
    New With {.controller = "Events", .action = "Index", .id = UrlParameter.Optional, .slug = UrlParameter.Optional} _
)

''# Alle ungültigen (Nicht gefunden) Routen
routes.MapRoute( _
    "NichtGefunden", _
    "{*url}", _
    New With {.controller = "Error", .action = "NotFound"})

Wenn Sie eingeben: http://example.com/asdf- Dann passt das zur obigen "Standard" - Route - MVC sucht nach asdf-Controller und kann es nicht finden, daher wird eine Ausnahme ausgelöst.

Wenn Sie zu http://example.com/asdf-/action/id/slug/extra gehen, entspricht "Standard" nicht mehr und stattdessen wird die "NichtGefunden" - Route verwendet.

Sie könnten für alle Ihre bekannten Controller einen Filter zur "Standard" - Route hinzufügen, aber das wird mühsam sein, wenn Sie neue Controller hinzufügen.

Sie sollten überhaupt nicht in das Application_Error - Ereignis eingreifen müssen, aber ich habe noch keinen besseren Weg um den fehlenden Controller herum gefunden - ich habe es als weitere Frage gestellt.

1voto

Faust Punkte 14241

Ich habe das hinbekommen, indem ich einfach die im Basiskontroller definierte Aktion zurückgebe, anstatt darauf umzuleiten.

[HandleError]
public ActionResult NotFound()
{
    Response.StatusCode = 404;
    Response.TrySkipIisCustomErrors = true;     
    return View("PageNotFound", SearchUtilities.GetPageNotFoundModel(HttpContext.Request.RawUrl));          
}

(Der Teil "SearchUtilities.GetPageNotFoundModel" dient dazu, Vorschläge zu erstellen, indem die URL in unsere Suchmaschine eingegeben wird.)

In jedem Aktionsmethode, die den Basiskontroller erbt, kann ich einfach dies aufrufen:

return NotFound();

... wenn ich einen ungültigen Parameter abfange. Und die allgemeine Route macht dasselbe.

0voto

Chris Kooken Punkte 31616

Richten Sie es in der Webkonfiguration ein:

error.html ist Ihre benutzerdefinierte Seite, auf der Sie beliebiges HTML für den Benutzer anzeigen können.

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