Dlaczego pojawia się komunikat „Nie można przekierować po wysłaniu nagłówków HTTP”, gdy wywołuję Response.Redirect ()?

84

Kiedy dzwonię Response.Redirect(someUrl), otrzymuję następujący HttpException:

Nie można przekierować po wysłaniu nagłówków HTTP.

Dlaczego to rozumiem? Jak mogę rozwiązać ten problem?

Samuel Meacham
źródło

Odpowiedzi:

120

Zgodnie z dokumentacją MSDN dla Response.Redirect(string url), zgłosi HttpException, gdy „podjęto próbę przekierowania po wysłaniu nagłówków HTTP”. Ponieważ Response.Redirect(string url)używa nagłówka odpowiedzi HTTP „Location” ( http://en.wikipedia.org/wiki/HTTP_headers#Responses ), wywołanie go spowoduje wysłanie nagłówków do klienta. Oznacza to, że jeśli wywołasz go po raz drugi lub jeśli wywołasz go po tym, jak spowodowałeś wysłanie nagłówków w inny sposób, otrzymasz HttpException.

Jednym ze sposobów na uniknięcie wielokrotnego wywoływania Response.Redirect () jest sprawdzenie Response.IsRequestBeingRedirectedwłaściwości (bool) przed jej wywołaniem.

// Causes headers to be sent to the client (Http "Location" response header)
Response.Redirect("http://www.stackoverflow.com");
if (!Response.IsRequestBeingRedirected)
    // Will not be called
    Response.Redirect("http://www.google.com");
Samuel Meacham
źródło
2
Tak, dokładnie. Dzieje się to dość łatwo w przypadku ASP.NET MVC 4 i filtrów wyjątków itp. Nie można również zmienić kodu stanu odpowiedzi HTTP po wydaniu przekierowania 301/302.
Jaans
Rozwiązałem ten problem, ustawiając wszystkie właściwości na mojej stronie jako „statyczne”
Sal
4
unieruchomienie nieruchomości jest niebezpiecznym rozwiązaniem
poszukiwacz
Jak można wywołać przekierowanie po raz drugi, chyba że wyjątek ThreadAbortException (od pierwszego) zostanie przechwycony? :} „Wywołanie Redirect jest równoważne wywołaniu Redirect z drugim parametrem ( endResponse) ustawionym na true”.
user2864740
1
To dziwne, ale w starszej aplikacji formularzy internetowych Response.IsRequestBeingRedirectedjest fałszywa i nadal otrzymuję ten sam wyjątek (wewnątrz Application_EndRequestmetody zdarzenia w Global.asax). Nie rozumiem dlaczego.
Alisson
17

Gdy w ogóle wyślesz jakąkolwiek zawartość do klienta, nagłówki HTTP zostały już wysłane. ZAResponse.Redirect()Wezwanie działa poprzez wysłanie specjalnego informacje w nagłówkach, które sprawiają, że przeglądarka poprosić o inny URL.

Ponieważ nagłówki zostały już wysłane, asp.net nie może robić tego, co chcesz (modyfikować nagłówki)

Możesz obejść ten problem, wykonując a) przekierowanie, zanim zrobisz cokolwiek innego, lub b) spróbuj użyć go, Response.Buffer = truezanim zrobisz cokolwiek innego, aby upewnić się, że żadne dane wyjściowe nie są wysyłane do klienta, dopóki cała strona nie zostanie wykonana.

Philip Rieck
źródło
U mnie to nie działa. Używam .NET, MVC i mam wywołanie wewnątrz metody kontrolera. Nadal otrzymuję wyjątek, chociaż zdarza się przekierowanie.
FrenkyB
8

Przekierowanie może się zdarzyć tylko wtedy, gdy pierwsza linia wiadomości HTTP to „HTTP/1.x 3xx Redirect Reason ”.

Jeśli już zadzwoniłeś Response.Write()lub ustawiłeś jakieś nagłówki, na przekierowanie będzie za późno. Możesz spróbować zadzwonić Response.Headers.Clear()przed przekierowaniem, aby sprawdzić, czy to pomoże.

Mark Cidade
źródło
Używam return RedirectToAction("Logout", "Authentication");i otrzymuję ten błąd
Kiquenet
Kiedy próbowałem wyczyścić nagłówki, otrzymałem System.PlatformNotSupportedException: Ta operacja wymaga trybu zintegrowanego potoku usług IIS.
IrishChieftain
3

Po prostu sprawdź, czy ustawiłeś opcję buforowania na false (domyślnie jest to prawda). Aby uzyskać odpowiedź. Przekierować do pracy,

  1. Buforowanie powinno być prawdziwe,
  2. nie powinieneś był wysyłać więcej danych przy użyciu response.write, który przekracza domyślny rozmiar bufora (w takim przypadku opróżni się, powodując wysłanie nagłówków), co uniemożliwia ci przekierowanie.

źródło
1
Response.BufferOutput = true;w akcji, w kontrolerze?
Kiquenet
2

Używanie return RedirectPermanent(myUrl)zadziałało dla mnie

Vasilis
źródło
Mam Akcję i Kontroler
Kiquenet
2

Możesz również użyć poniższego kodu

Response.Write("<script type='text/javascript'>"); Response.Write("window.location = '" + redirect url + "'</script>");Response.Flush();
Dipanki Jadav
źródło
1

Jest na to jedna prosta odpowiedź: otrzymałeś coś innego, na przykład tekst lub cokolwiek związanego z wyjściem ze strony przed wysłaniem nagłówka. Ma to wpływ na to, dlaczego pojawia się ten błąd.

Po prostu sprawdź swój kod pod kątem możliwych wyników lub możesz umieścić nagłówek na górze metody, aby został wysłany jako pierwszy.

DucDigital
źródło
1

Jeśli próbujesz przekierować po wysłaniu nagłówków (jeśli na przykład robisz błąd przekierowania z częściowo wygenerowanej strony), możesz wysłać klientowi Javascript (location.replace lub location.href itp.) aby przekierować na dowolny adres URL. Oczywiście zależy to od tego, jaki HTML został już przesłany.

Ćwiek
źródło
1

Mój problem został rozwiązany przez dodanie programu obsługi wyjątków do obsługi „Nie można przekierować po wysłaniu nagłówków HTTP”. ten błąd, jak pokazano poniżej

catch (System.Threading.ThreadAbortException)
        {
            // To Handle HTTP Exception "Cannot redirect after HTTP headers have been sent".
        }
        catch (Exception e)
        {//Here you can put your context.response.redirect("page.aspx");}
SamsonOnNet
źródło
1

Rozwiązałem problem przy użyciu: Response.RedirectToRoute ("CultureEnabled", RouteData.Values); zamiast Response.Redirect.

utilsit
źródło
1

Błąd Nie można przekierować po wysłaniu nagłówków HTTP.

System.Web.HttpException (0x80004005): nie można przekierować po wysłaniu nagłówków HTTP.

Sugestia

Jeśli używamy asp.net mvc i pracujemy na tym samym kontrolerze i przekierowujemy do innej akcji, nie ma potrzeby pisania ..
Response.Redirect ("ActionName", "ControllerName");
lepiej jest używać tylko
return RedirectToAction ("ActionName");
lub
return View („ViewName”);

Ram Samuj
źródło
Używam ActionName z innego ControllerName?
Kiquenet
0

Funkcja przekierowania prawdopodobnie działa przy użyciu „odświeżania” nagłówka http (i być może przy użyciu kodu 30X). Po wysłaniu nagłówków do klienta serwer nie może dołączyć polecenia przekierowania, ponieważ jest już za późno.

Nathan
źródło
0

Jeśli pojawi się komunikat Nie można przekierować po wysłaniu nagłówków HTTP, wypróbuj poniższy kod.

HttpContext.Current.Server.ClearError();
// Response.Headers.Clear();
HttpContext.Current.Response.Redirect("/Home/Login",false);
Aashish Garg
źródło
0

Upewnij się, że nie używasz Responsemetod s, takich jak Response.Flush();przed częścią przekierowującą.

1_bug
źródło
-3

Istnieją 2 sposoby, aby to naprawić:

  1. Po prostu dodaj returnoświadczenie po swoimResponse.Redirect(someUrl); (jeśli podpis metody nie jest "void", będziesz oczywiście musiał zwrócić ten "typ"), tak jak to:

    Response.Redirect ("Login.aspx");

    powrót;

Zwróć uwagę, że powrót umożliwia serwerowi wykonanie przekierowania ... bez niego serwer chce kontynuować wykonywanie reszty kodu ...

  1. Utwórz Response.Redirect(someUrl)OSTATNI wykonaną instrukcję w metodzie, która zgłasza wyjątek. Zastąp swój Response.Redirect(someUrl)ciąg VARIABLE o nazwie „someUrl” i ustaw go na lokalizację przekierowania ... w następujący sposób:

//......some code

string someUrl = String.Empty

..... trochę logiki

if (x=y)
{
    // comment (original location of Response.Redirect("Login.aspx");)
    someUrl = "Login.aspx";
}

...... więcej kodu

// PRZENIEŚ swoją odpowiedź Przekieruj do TUTAJ (koniec metody):

Response.Redirect(someUrl);
return; 
user9150083
źródło
przepraszam, ale to nie ma dla mnie żadnego sensu. Co powinno zrobić (w metodzie zwracającej pustkę), co zbędne return? returnTylko określa, że metoda jest zakończona. Ale jeśli nie ma już żadnego kodu, metoda i tak jest zakończona. A przechowywanie adresu URL w zmiennej niczego nie zmienia, to znaczy: po co? Ciąg jest taki sam. Skompilowana rzecz nie robi żadnej różnicy między napisem a zmienną zawierającą łańcuch ...: pomyśl o tym x = 5, więc x to 5, ale 5 to także 5. Nawet 10/2 to 5 ... też nie robi różnicy
Matthias Burger