it-swarm.com.de

Der Server kann den Status nicht festlegen, nachdem die HTTP-Header IIS7.5 gesendet wurden

Manchmal bekomme ich in meiner Produktionsumgebung eine Ausnahme:

  • Prozessinformationen
    • Prozess-ID: 3832 
    • Prozessname: w3wp.exe 
    • Kontoname: NT AUTHORITY\NETWORK SERVICE 
  • Ausnahmeinformationen
    • Ausnahmetyp: System.Web.HttpException 
    • Ausnahmemeldung: Server kann den Status nicht festlegen, nachdem HTTP-Header gesendet wurden. 
  • Anfrage Informationen
    • Anforderungs-URL: http://www.myulr.pl/logon
    • Anforderungspfad:/login 
    • Benutzerhostadresse: 10.11.9.1 
    • Benutzer: user001 
    • Wird authentifiziert: Richtig 
    • Authentifizierungstyp: Formulare 
    • Thread-Kontoname: NT AUTHORITY\NETWORK SERVICE 
  • Thread-Information
    • Thread-ID: 10 
    • Thread-Kontoname: NT AUTHORITY\NETWORK SERVICE 
    • Ist imitatorisch: falsch 
Stack trace: at System.Web.HttpResponse.set_StatusCode(Int32 value) at  
System.Web.HttpResponseWrapper.set_StatusCode(Int32 value) at  
System.Web.Mvc.HandleErrorAttribute.OnException(ExceptionContext filterContext) at  
System.Web.Mvc.ControllerActionInvoker.InvokeExceptionFilters(ControllerContext controllerContext, IList(1) filters, Exception exception) at  
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) at System.Web.Mvc.Controller.ExecuteCore() at  
System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__4() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0() at  
System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8(1).<BeginSynchronous>b__7(IAsyncResult _) at  
System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult(1).End() at   
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) at  
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at  
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& ompletedSynchronously) 

Ich habe diesen Fehler in meiner Testumgebung nicht bemerkt. Was sollte ich überprüfen?

Ich verwende ASP.NET MVC 2 (Release Candidate 2) 

67
marcinn

Ich stimme Vagrant hinsichtlich der Sache weitgehend zu:

  1. ihre Aktion wurde ausgeführt und das Markup in den Antwortstream geschrieben
  2. der Stream wurde nicht gepuffert, so dass die Antwortheader geschrieben wurden, bevor mit dem Schreiben von Markup begonnen werden konnte.
  3. Ihre Ansicht ist auf einen Laufzeitfehler gestoßen
  4. Der Ausnahmehandler versucht, den Statuscode auf einen anderen Wert als 200 zu setzen
  5. Schlägt fehl, da die Header bereits gesendet wurden. 

Wobei ich mit Vagrant nicht einverstanden bin, ist das "Beheben von Fehlern beim Binden" eine Lösung. Nullreferenzausnahmen.

Eine bessere Lösung hierfür ist, sicherzustellen, dass Response.BufferOutput = true; vor dem Senden von Bytes an den Antwortstream gesendet wird. z.B. in Ihrer Controller-Aktion oder On_Begin_Request in der Anwendung. Auf diese Weise können Server-Transfers, Cookies/Header usw. gesetzt werden, bis hin zur natürlich endenden Antwort oder zum Aufrufen von Ende/Flush. 

Natürlich sollte auch überprüft werden, ob der Puffer nicht weiter unten im Stack geleert/auf false gesetzt wird.

MSDN-Referenz: HttpResponse.BufferOutput

58
stephbu

Einfach zu den Antworten oben hinzufügen. Ich hatte das gleiche Problem, als ich zum ersten Mal mit ASP.Net MVC begann und während einer Controller-Aktion eine Response.Redirect-Funktion ausführte:

Response.Redirect("/blah", true);

Anstatt eine Response.Redirect-Aktion zurückzugeben, hätte ich eine RedirectAction zurückgeben sollen:

return Redirect("/blah");
45
Doug

Der HTTP-Server sendet den Antwortheader erst an den Client zurück, wenn Sie entweder einen Fehler angeben oder mit dem Senden von Daten beginnen. Wenn Sie anfangen, Daten an den Client zurückzuschicken, muss der Server zuerst den Antwortkopf (der den Statuscode enthält) senden. Nachdem der Header gesendet wurde, können Sie offensichtlich keinen Statuscode mehr in den Header einfügen.

Hier ist das übliche Problem. Sie starten die Seite und senden einige Anfangs-Tags (d. H. <head>). Der Server sendet diese Tags dann an den Client, nachdem er zuerst den HTTP-Antwortheader mit dem angenommenen Status SUCCESS gesendet hat. Jetzt fangen Sie an, an dem Fleisch der Seite zu arbeiten, und entdecken ein Problem. Sie können an dieser Stelle keinen Fehler senden, da der Antwortheader, der den Fehlerstatus enthalten würde, bereits gesendet wurde.

Die Lösung ist folgende: Bevor Sie Inhalte generieren, prüfen Sie, ob Fehler auftreten. Erst wenn Sie versichert haben, dass es keine Probleme gibt, können Sie mit dem Senden von Inhalten wie dem Tag beginnen.

In Ihrem Fall scheint es, als hätten Sie eine Anmeldeseite, die eine POST -Anforderung eines Formulars verarbeitet. Sie werfen wahrscheinlich etwas anfängliches HTML aus und überprüfen dann, ob Benutzername und Passwort gültig sind. Stattdessen sollten Sie zuerst den Benutzer/das Kennwort authentifizieren, bevor Sie any HTML generieren.

15
Vagrant

Ich hatte das gleiche Problem mit der Einstellung StatusCode und dann Response.End in der HandleUnauthorizedRequest-Methode von AuthorizeAttribute

var ctx = filterContext.HttpContext;
ctx.Response.StatusCode = (int)HttpStatusCode.Forbidden;
ctx.Response.End();

Wenn Sie .NET 4.5 oder höher verwenden, fügen Sie diese Zeile vor Response.StatusCode ein.

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

Wenn Sie .NET 4.0 verwenden, versuchen Sie SuppressFormsAuthenticationRedirectModule .

11
VahidN

Überprüfen Sie dies, bevor Sie die Weiterleitung durchführen:

if (!Response.IsRequestBeingRedirected)
{
   //do the redirect
}
10
Sandeep

Sie versuchen tatsächlich, eine Seite umzuleiten, auf die eine Antwort zu werfen ist. Zuerst bewahren Sie die Informationen, die Sie mit response.buffer = true am Anfang der Seite in einen Puffer werfen, und leeren sie dann bei Bedarf mit response.flush. Dieser Fehler wird behoben

3
hema

Ich erinnere mich an den Teil aus dieser Ausnahme: "Header-Informationen können nicht geändert werden - Header bereits gesendet von", die in PHP auftreten. Es trat auf, wenn die Header bereits in der Umleitungsphase gesendet wurden und eine andere Ausgabe generiert wurde, z.

echo "Hallo"; Header ("Location: http://stackoverflow.com ");

Verzeihen Sie und korrigieren Sie mich, wenn ich falsch liege, aber ich lerne immer noch MS Technologies und habe versucht zu helfen.

1
Adil Mehmood

Ich entschuldige mich, aber ich füge dem Thread meine 2 Cent hinzu, nur für den Fall, dass jemand das gleiche Problem hat.

  • Ich habe in meiner MVC-App die Formularauthentifizierung verwendet
  • Einige Controller-Aktionen waren jedoch "anonym", d. H. Nicht authentifizierten Benutzern
  • Manchmal möchte ich in diesen Aktionen still, dass Benutzer unter bestimmten Bedingungen zum Anmeldeformular umgeleitet werden
  • um dies zu tun - ich habe dies in meiner Aktionsmethode: return new HttpStatusCodeResult(401) - und ASP.NET ist super nett, dies zu erkennen und leitet den Benutzer auf die Anmeldeseite um! Magie, richtig? Es hat sogar den richtigen ReturnUrl-Parameter usw.

Aber siehst du, wo ich herkomme? Ich kehre 401 zurück. Und ASP.NET leitet den Benutzer um. Welches ist im Wesentlichen gibt 302 zurück. Ein Statuscode wird durch einen anderen ersetzt.

Und einige IIS -Server (nur einige!) Lösen diese Ausnahme aus. Manche tun es nicht. - Ich habe es nicht auf meinem Testserver, nur auf meinem Produktionsserver (ist es nicht immer der Fall, o_O)

Ich weiß, dass meine Antwort im Wesentlichen wiederholt, was hier bereits gesagt wurde, aber manchmal ist es schwer herauszufinden, wo genau diese Überschreibung stattfindet.

1
jazzcat

Wir haben den gleichen Fehler erhalten - daher kann dies für einige nützlich sein.

Für uns war die Sache super einfach. Eine Benutzeroberflächenänderung verwirrte einen Endbenutzer, und der Benutzer drückte nach einer Formularübergabe zu einem 'schlechten' Zeitpunkt den Zurück-Button im Browser (sicher hätten wir wahrscheinlich ein PRG-Muster verwenden sollen, was wir jedoch nicht getan haben).

Wir haben das Problem behoben und der Benutzer drückt nicht mehr die Zurück-Taste. Problem gelöst.

0
niico

Wenn jemand dieses Problem immer noch hat. Versuchen Sie es statt zu überschreiben

 public void OnActionExecuting(ActionExecutingContext context)
    {
        try
        {

            if (!HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (!HttpContext.Current.Response.IsRequestBeingRedirected)
                {

                    context.Result = new RedirectToRouteResult(
                new RouteValueDictionary {  { "controller", "Login" }, { "action", "Index" } });
                }
            }

        }
        catch (Exception ex)
        {
               new RouteValueDictionary { { "controller", "Login" }, { "action", "Index" } });
        }

    }
0
Emre