wake-up-neo.com

IIS7 überschreibt customErrors beim Setzen von Response.StatusCode?

Ich habe hier ein komisches Problem. Jeder weiß, dass Sie, wenn Sie den Abschnitt customErrors von web.config verwenden, um eine benutzerdefinierte Fehlerseite zu erstellen, Ihren Response.StatusCode auf den geeigneten Wert setzen müssen. Wenn ich beispielsweise eine benutzerdefinierte 404-Seite erstelle und sie 404.aspx benenne, könnte ich <% Response.StatusCode = 404 %> in den Inhalt einfügen, damit sie einen echten 404-Statusheader hat.

Folge mir so weit? Gut. Versuchen Sie dies jetzt auf IIS7. Ich kann es nicht zur Arbeit bringen, Punkt. Wenn Response.StatusCode auf der benutzerdefinierten Fehlerseite festgelegt ist, scheint IIS7 die benutzerdefinierte Fehlerseite vollständig zu überschreiben und zeigt eine eigene Statusseite an (sofern Sie eine konfiguriert hat.)

Hat jemand anderes dieses Verhalten gesehen und vielleicht auch gewusst, wie man es umgehen kann? Es arbeitete unter IIS6, daher weiß ich nicht, warum sich die Dinge geändert haben.

Hinweis: Dies ist nicht dasselbe wie das Problem in ASP.NET Custom 404, das 200 anstelle von 404 zurückgibt. OK nicht gefunden

97
Nicholas Head

Setzen Sie in dem Abschnitt system.webServer/httpErrors die vorhandene Antwort auf PassThrough:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

Der Standardwert der Eigenschaft existsResponse lautet Auto: 

Auto weist das benutzerdefinierte Fehlermodul an, die Funktion right auszuführen. Der tatsächliche von Clients erfasste Fehlertext ist abhängig vom Wert von fTrySkipCustomErrors, die in IHttpResponse::GetStatus-Aufruf zurückgegeben werden. Wenn fTrySkipCustomErrors auf true gesetzt ist, lässt das benutzerdefinierte Fehlermodul die Antwort durch. Wenn es jedoch auf false gesetzt ist, ersetzt das benutzerdefinierte Fehlermodul Text durch seinen eigenen Text.

Weitere Informationen: Was Sie von einem benutzerdefinierten IIS7-Fehlermodul erwarten können

115
Pavel Chuchuva

Der einfachste Weg, das Verhalten konsistent zu machen, besteht darin, den Fehler zu löschen und Response.TrySkipIisCustomErrors zu verwenden und auf true zu setzen. Dadurch wird die globale Fehlerseitenbehandlung IIS auf Ihrer Seite oder der globale Fehlerhandler in Application_Error überschrieben.

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

Normalerweise sollten Sie dies in Ihrem Application_Error-Handler tun, der alle Fehler behandelt, die von Ihren Anwendungsfehlerhandlern nicht erkannt werden.

Ausführlichere Informationen finden Sie in diesem Blogeintrag: http://www.west-wind.com/weblog/posts/745738.aspx

80
Rick Strahl

Gelöst: Es stellt sich heraus, dass "Detailed Errors" aktiviert sein muss, damit IIS7 jede Fehlerseite "durchläuft". Siehe http://forums.iis.net/t/1146653.aspx

11
Nicholas Head

Ich bin mir nicht sicher, ob das ähnlich ist oder nicht, aber ich habe ein Problem gelöst, das sich an der Oberfläche ähnlich anhört und hier ist, wie ich damit umgegangen bin. 

Zuallererst war der Standardwert für existsResponse (Auto) in meinem Fall die richtige Antwort, da ich benutzerdefinierte 404, 400 und 500 habe (ich könnte andere erstellen, aber diese drei reichen für das, was ich tue). Hier sind die relevanten Abschnitte, die mir geholfen haben.

Von web.config:

<customErrors mode="Off" />

Und

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

Von dort habe ich dies in Application_Error auf global.asax hinzugefügt:

    Response.TrySkipIisCustomErrors = True

Auf jeder meiner benutzerdefinierten Fehlerseiten musste ich den korrekten Antwortstatuscode angeben. In meinem Fall verwende ich eine benutzerdefinierte 404, um Benutzer zu verschiedenen Abschnitten meiner Website zu senden. Ich möchte, dass nicht einen 404-Statuscode zurückgegeben wird, sofern es sich nicht um eine tote Seite handelt. 

So habe ich es auch gemacht. Hoffe das hilft jemandem.

4
SEFL

Dieses Problem hat erhebliche Kopfschmerzen verursacht. Keiner der zuvor genannten Vorschläge allein hat es für mich gelöst, daher füge ich meine Lösung hinzu. Für die Aufzeichnung verwendet unsere Umgebung/Plattform:

  • .NET Framework 4
  • MVC 3
  • IIS8 (Arbeitsstation) und IIS7 (Webserver)

Insbesondere habe ich versucht, eine HTTP-404-Antwort zu erhalten, die den Benutzer zu unserer benutzerdefinierten 404-Seite umleitet (über die Web.config-Einstellungen).

Zuerst musste mein Code eine HttpException werfen. Die Rückgabe einer NotFoundResult vom Controller hat nicht die Ergebnisse erzielt, nach denen ich gesucht habe.

throw new HttpException(404, "There is no class with that subject");

Dann musste ich beide die Knoten customErrors und httpError in der Web.config konfigurieren.

<customErrors mode="On" defaultRedirect="/classes/Error.aspx">
  <error statusCode="404" redirect="/classes/404.html" />
</customErrors>

...

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
</httpErrors>

Beachten Sie, dass ich die existingResponse als Auto belassen habe, was sich von der Lösung @sefl unterscheidet.

Die customErrors-Einstellungen schienen für die Handhabung meiner explizit geworfenen HttpException notwendig zu sein, während der httpErrors-Knoten URLs behandelte, die außerhalb der in Globals.asax.cs angegebenen Routenmuster lagen.

P.S. Mit diesen Einstellungen musste ich Response.TrySkipIisCustomErrors nicht einstellen

3
Shawn South

Standardmäßig verwendet IIS 7 ausführliche benutzerdefinierte Fehlermeldungen. Ich würde also davon ausgehen, dass Response.StatusCode 404.XX und nicht nur 404 entspricht.

Sie können IIS7 so konfigurieren, dass die einfacheren Fehlermeldungscodes verwendet werden, oder Sie können den Code ändern, der die detaillierteren Fehlermeldungen von IIS7 verarbeitet.

Weitere Informationen finden Sie hier: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

Weitere Untersuchungen haben ergeben, dass ich es falsch verstanden habe - detaillierte Meldungen sind nicht standardmäßig eingestellt, aber möglicherweise wurden sie aktiviert, wenn Sie die verschiedenen Fehlermeldungen sehen, die Sie erwähnt haben.

0
nullnvoid

TrySkipIisCustomErrors ist nur ein Teil eines Puzzles. Wenn Sie benutzerdefinierte Fehlerseiten verwenden, aber auch einige REST-fähige Inhalte basierend auf 4xx-Status bereitstellen möchten, liegt ein Problem vor. Die Einstellung httpErrors.existingResponse von web.config auf "Auto" funktioniert nicht, da .net anscheinend immer einige Seiteninhalte an IIS liefert. Daher werden bei Verwendung von "Auto" nicht alle (oder zumindest einige) benutzerdefinierte Fehlerseiten verwendet. Die Verwendung von "Ersetzen" funktioniert ebenfalls nicht, da die Antwort Ihren http-Statuscode enthält, der Inhalt jedoch leer ist oder mit einer benutzerdefinierten Fehlerseite gefüllt ist. Und das "PassThrough" schaltet das KEP aus, sodass es nicht verwendet werden kann.

Wenn Sie also CEP in einigen Fällen umgehen möchten (unter Umgehung des Status 4xx mit einigem Inhalt), benötigen Sie einen zusätzlichen Schritt: Bereinigen Sie den Fehler:

void Application_Error(object sender, EventArgs e)
{
    var httpException = Context.Server.GetLastError() as HttpException;
    var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;

    Context.Server.ClearError();
    Context.Response.StatusCode = statusCode;
}

Wenn Sie also die Antwort REST verwenden möchten (z. B. 400 - Bad Request) und einige Inhalte mitsenden möchten, müssen Sie lediglich TrySkipIisCustomErrors irgendwo in Aktion setzen und existingResponse im Abschnitt "httpErrors" in web.config auf "Auto" setzen . Jetzt:

  • wenn kein Fehler vorliegt (Aktion gibt 4xx oder 5xx zurück) und einige Inhalte werden zurückgegeben, wird der CEP nicht verwendet und der Inhalt wird an den Client übergeben.
  • wenn ein Fehler auftritt (eine Ausnahme wird ausgelöst), wird der von den Fehlerbehandlungsroutinen zurückgegebene Inhalt entfernt, sodass der CEP verwendet wird.

Wenn Sie den Status mit leerem Inhalt aus Ihrer Aktion zurückgeben möchten, wird dies als leere Antwort behandelt und CEP wird angezeigt. Es gibt also noch Raum, diesen Code zu verbessern.

0