ASP.NET Custom 404 Rückgabe von 200 OK anstelle von 404 Nicht gefunden


80

Nachdem ich versucht hatte, meine Website für die Google Webmaster-Tools einzurichten, stellte ich fest, dass meine benutzerdefinierte ASP.NET 404-Seite den 404-Statuscode nicht zurückgab. Es zeigte die richtige benutzerdefinierte Seite an und teilte dem Browser mit, dass alles in Ordnung ist. Dies ist eine weiche 404 oder eine falsche 404. Google gefällt das nicht. Ich habe also viele Artikel zu diesem Thema gefunden, aber die gewünschte Lösung schien nicht zu funktionieren.

Die Lösung, an der ich arbeiten möchte, besteht darin, dem Code hinter der Page Load-Methode der benutzerdefinierten 404-Seite die folgenden zwei Zeilen hinzuzufügen.

Response.Status = "404 Not Found";
Response.StatusCode = 404;

Das funktioniert nicht. Die Seite gibt immer noch 200 OK zurück. Ich fand jedoch heraus, dass, wenn ich den folgenden Code hart in den Design-Code codiere, er ordnungsgemäß funktioniert.

<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">

<%
    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
%>

 ... Much more code ...

</asp:content>

Die Seite verwendet eine Masterseite. Und ich konfiguriere benutzerdefinierte Fehlerseiten in meiner web.config. Ich würde wirklich lieber den Code hinter der Option verwenden, aber ich kann nicht scheinen, dass es funktioniert, ohne den Hack-Inline-Code in das Design / Layout einzufügen.


Was sagt der Browser? Ich benutze das Addon Header Spy für Firefox.
Bobby Cannon

Antwort des Header-Spions: HTTP / 1.1 404 Nicht gefunden Datum: So, 07. Dezember 2008, 06:21:20 Uhr GMT
Ryan Cook,

Verwenden Sie eine Masterseite? Vielleicht ist es das. Ich werde eine Seite ohne Verwendung einer Masterseite versuchen ...
Bobby Cannon

Nein, war ich nicht, aber ich kann auch eine schnelle Überprüfung durchführen, ich werde es mit einer versuchen.
Ryan Cook

Ja, das ist es! Die Masterseite verursachte ein 200 OK
Ryan Cook

Antworten:


72

Lösung:

Es stellte sich heraus, dass das Problem die Verwendung der Masterseite war. Ich habe es zum Laufen gebracht, indem ich den Statuscode später im Seitenlebenszyklus festgelegt habe. Offensichtlich wurde das Rendern der Masterseite zurückgesetzt, also habe ich die Rendermethode überschrieben und festgelegt, nachdem das Rendern abgeschlossen war.

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    Response.StatusCode = 404;
}

Es könnte noch mehr Arbeit geleistet werden, um herauszufinden, wann die Masterseite den Status festlegt, aber das überlasse ich Ihnen.


Ursprünglicher Beitrag:

Ich konnte eine Test-Web-App zum Laufen bringen, die zumindest die benutzerdefinierte Fehlerseite anzeigte und einen 404-Statuscode zurückgab. Ich kann Ihnen nicht sagen, was mit Ihrer App nicht stimmt, aber ich kann Ihnen sagen, was ich getan habe:

1) Die web.config wurde für benutzerdefinierte Fehler bearbeitet:

<customErrors mode="On">
  <error statusCode="404" redirect="404.aspx"/>
</customErrors>

2) Eine 404.aspx-Seite wurde hinzugefügt und der Statuscode auf 404 gesetzt.

public partial class _04 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
}

Das ist es, wenn ich zu einer Seitenerweiterung gehe, die von Asp.Net verarbeitet wird und nicht existiert, zeigt mein Geigerprotokoll eindeutig eine 404, hier ist die Kopfzeile:

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/5.1
Date: Sun, 07 Dec 2008 06:04:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 533

Wenn ich jetzt zu einer Seite gehe, die nicht von Asp.Net verarbeitet wird, wie eine HTML-Datei, wird die benutzerdefinierte Seite nicht angezeigt und der von IIS konfigurierte 404 wird angezeigt.

Hier ist ein Beitrag, der einige weitere Details behandelt, die für Sie und Ihr Problem von Nutzen sein können. Mein Test führt eine Umleitung zur neuen Seite durch, sodass die URL der angeforderten Datei so gut wie verloren geht (außer in der Abfragezeichenfolge). .

Benutzerdefinierte Fehlerseiten für Google 404 und .NET

Antwort des Header-Spions:

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT

4
Header Spy ist Addon Header Spy für Firefox
Kiquenet

Wie funktioniert das für statische .htmlbenutzerdefinierte Fehlerseiten?
Ebyrob

28

Ich hatte ein ähnliches Problem. Ich möchte eine benutzerdefinierte Seite als 404 (ASPX) anzeigen und es funktionierte einwandfrei auf localhost, aber sobald ein entfernter Besucher eine Verbindung herstellte, erhielten sie den generischen IIS 404.

Die Lösung hierfür war das Hinzufügen

Response.TrySkipIisCustomErrors = true;

Vor dem Ändern des Response.StatusCode.

Gefunden über Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx


12

Die IIS 7-Lösung besteht darin, dies einfach zu Ihrer web.config-Datei hinzuzufügen:

<system.webServer>
  <httpErrors existingResponse="Replace">
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="404.htm" responseMode="File" />
    <error statusCode="500" prefixLanguageFilePath="" path="500.htm" responseMode="File" />
  </httpErrors>
</system.webServer>

http://forums.asp.net/t/1563128.aspx/1


3
Hat für mich gearbeitet! Die einzige Lösung hier hat funktioniert, wahrscheinlich aufgrund der Version, die Sie notieren ... Beachten Sie: Sie können mit dieser Lösung nur statische .htm-Dateien verwenden.
Squarecandy

11

Versuchen Sie, Response.End () aufzurufen, um das Rendern zu überspringen ...

Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;

9

Nach vielen Tests und Fehlerbehebungen scheint es, dass bestimmte Hosting-Anbieter den Rückkehrcode stören können. Ich konnte dies umgehen, indem ich einen "Hack" in den Inhalt anwendete.

<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>

Auf diese Weise kann die Seite unabhängig davon den richtigen Rückkehrcode zurückgeben.


1

Ich konnte dieses Problem umgehen, indem ich das folgende Setup in asp.net-Webformularen mit .NET 3.5 verwendete.

Das von mir implementierte Muster umgeht die benutzerdefinierte Umleitungslösung von .NET in der web.config, da ich meine eigene geschrieben habe, um alle Szenarien mit dem richtigen HTTP-Statuscode im Header zu behandeln.

Zunächst sieht der Abschnitt customErrors der web.config folgendermaßen aus:

<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />

Dieses Setup stellt sicher, dass der CustomErrors-Modus aktiviert ist, eine Einstellung, die wir später benötigen, und bietet eine Option für alle anderen Fehler für die defaultRedirect von error.htm. Dies ist nützlich, wenn ich keinen Handler für den spezifischen Fehler habe oder wenn eine Datenbankverbindung unterbrochen ist.

Zweitens ist hier das globale Asax-Fehlerereignis:

protected void Application_Error(object sender, EventArgs e)
    {
       HandleError();
    }

    private void HandleError()
    {
        var exception = Server.GetLastError();
        if (exception == null) return;

        var baseException = exception.GetBaseException();

        bool errorHandled = _applicationErrorHandler.HandleError(baseException);
        if (!errorHandled) return;


        var lastError = Server.GetLastError();
    if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
        Server.ClearError();
    }
    }

Dieser Code gibt die Verantwortung für die Behandlung des Fehlers an eine andere Klasse weiter. Wenn der Fehler nicht behandelt und CustomErrors aktiviert ist, bedeutet dies, dass wir einen Fall haben, in dem wir in Produktion sind und ein Fehler irgendwie nicht behandelt wurde. Wir werden es hier löschen, um zu verhindern, dass der Benutzer es sieht, aber melden Sie es in Elmah an, damit wir wissen, was los ist.

Die applicationErrorHandler-Klasse sieht folgendermaßen aus:

public bool HandleError(Exception exception)
        {
            if (exception == null) return false;

            var baseException = exception.GetBaseException();

            Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);

            if (!HttpContext.Current.IsCustomErrorEnabled) return false;

            try
            {

                var behavior = _responseBehaviorFactory.GetBehavior(exception);
                if (behavior != null)
                {
                    behavior.ExecuteRedirect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
            return false;
        }

Diese Klasse verwendet im Wesentlichen das Befehlsmuster, um den geeigneten Fehlerbehandler für den ausgegebenen Fehlertyp zu finden. Es ist wichtig, Exception.GetBaseException () auf dieser Ebene zu verwenden, da fast jeder Fehler in eine Ausnahme höherer Ebene eingeschlossen wird. Wenn Sie beispielsweise von einer Aspx-Seite aus "Neue System.Exception () auslösen" ausführen, wird auf dieser Ebene eine HttpUnhandledException empfangen, keine System.Exception.

Der "Factory" -Code ist einfach und sieht folgendermaßen aus:

public ResponseBehaviorFactory()
    {
        _behaviors = new Dictionary<Type, Func<IResponseBehavior>>
                        {
                            {typeof(StoreException), () => new Found302StoreResponseBehavior()},
                            {typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
                            {typeof(HttpException), () => new HttpExceptionResponseBehavior()},
                            {typeof(Exception), () => new Found302DefaultResponseBehavior()}
                        };
    }

    public IResponseBehavior GetBehavior(Exception exception)
    {                                                                               
        if (exception == null) throw new ArgumentNullException("exception");

        Func<IResponseBehavior> behavior;
        bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);

        //default value here:
        if (!tryGetValue)
            _behaviors.TryGetValue(typeof(Exception), out behavior);

        if (behavior == null)
            Elmah.ErrorSignal.FromCurrentContext().Raise(
                new Exception(
                    "Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
                    exception));
        return behavior();
    }

Am Ende habe ich ein erweiterbares Fehlerbehandlungsschema eingerichtet. In jedem der definierten "Verhaltensweisen" habe ich eine benutzerdefinierte Implementierung für den Fehlertyp. Beispielsweise wird eine HTTP-Ausnahme auf den Statuscode überprüft und entsprechend behandelt. Für einen 404-Statuscode ist ein Server.Transfer anstelle eines Request.Redirect erforderlich, zusammen mit dem entsprechenden Statuscode, der in den Header geschrieben ist.

Hoffe das hilft.


0

Sie können den folgenden Code verwenden:

 Response.TrySkipIisCustomErrors = True
 Response.Status = "404 Not Found"
 Response.AddHeader("Location", "{your-path-to-your-404-page}")
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.