Tại sao tôi nhận được thông báo “Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi đi” khi tôi gọi Response.Redirect ()?


84

Khi tôi gọi, Response.Redirect(someUrl)tôi nhận được HttpException sau:

Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi.

Tại sao tôi nhận được điều này? Và làm cách nào để khắc phục sự cố này?

Câu trả lời:


120

Theo tài liệu MSDN cho Response.Redirect(string url), nó sẽ ném ra một HttpException khi "chuyển hướng được cố gắng sau khi các tiêu đề HTTP đã được gửi". Vì Response.Redirect(string url)sử dụng tiêu đề phản hồi Http "Vị trí" ( http://en.wikipedia.org/wiki/HTTP_headers#Responses ), việc gọi nó sẽ khiến tiêu đề được gửi đến máy khách. Điều này có nghĩa là nếu bạn gọi nó lần thứ hai hoặc nếu bạn gọi nó sau khi bạn đã gửi tiêu đề theo cách khác, bạn sẽ nhận được HttpException.

Một cách để bảo vệ không gọi Response.Redirect () nhiều lần là kiểm tra thuộc Response.IsRequestBeingRedirectedtính (bool) trước khi gọi nó.

// 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");

2
Đúng vậy. Điều này xảy ra khá dễ dàng với ASP.NET MVC 4 và các bộ lọc Ngoại lệ, v.v. Bạn cũng không thể thay đổi Mã trạng thái phản hồi HTTP sau khi chuyển hướng 301/302 đã được phát hành.
Jaans

Tôi đã giải quyết vấn đề bằng cách đặt tất cả các thuộc tính trên trang của mình là 'tĩnh'
Sal

4
làm cho tính chất tĩnh của bạn là một giải pháp nguy hiểm
Prospector

Làm thế nào để chuyển hướng có thể được gọi lần thứ hai trừ khi ThreadAbortException (từ lần đầu tiên) bị bắt? :} "Gọi Redirect tương đương với việc gọi Redirect với tham số thứ hai ( endResponse) được đặt thành true."
dùng2864740

1
Thật kỳ lạ, nhưng trong một ứng dụng biểu mẫu web kế thừa Response.IsRequestBeingRedirectedlà sai và tôi vẫn nhận được cùng một ngoại lệ này (bên trong Application_EndRequestphương thức sự kiện trong Global.asax). Tôi không thể hiểu tại sao.
Alisson

17

Sau khi bạn gửi bất kỳ nội dung nào đến máy khách, tiêu đề HTTP đã được gửi. Cuộc Response.Redirect()gọi hoạt động bằng cách gửi thông tin đặc biệt trong tiêu đề khiến trình duyệt yêu cầu một URL khác.

Vì các tiêu đề đã được gửi, asp.net không thể làm những gì bạn muốn (sửa đổi các tiêu đề)

Bạn có thể giải quyết vấn đề này bằng cách a) thực hiện Chuyển hướng trước khi bạn làm bất kỳ điều gì khác, hoặc b) thử sử dụng Response.Buffer = truetrước khi bạn làm bất kỳ điều gì khác, để đảm bảo rằng không có đầu ra nào được gửi đến máy khách cho đến khi toàn bộ trang được thực thi xong.


Đối với tôi nó không hoạt động. Tôi sử dụng .NET, MVC và tôi có một cuộc gọi bên trong phương thức của bộ điều khiển. Tôi vẫn nhận được ngoại lệ, mặc dù chuyển hướng xảy ra.
FrenkyB 21/02/19

8

Chuyển hướng chỉ có thể xảy ra nếu dòng đầu tiên trong thông báo HTTP là " HTTP/1.x 3xx Redirect Reason".

Nếu bạn đã gọi Response.Write()hoặc đặt một số tiêu đề, sẽ quá muộn để chuyển hướng. Bạn có thể thử gọi Response.Headers.Clear()trước khi Chuyển hướng để xem điều đó có hữu ích không.


Tôi sử dụng return RedirectToAction("Logout", "Authentication");và tôi nhận được rằng lỗi
Kiquenet

Khi tôi thử xóa các tiêu đề, tôi nhận được System.PlatformNotSupportedException: Thao tác này yêu cầu chế độ đường ống tích hợp IIS.
AilenChieftain

3

Chỉ cần kiểm tra xem bạn đã đặt tùy chọn đệm thành false chưa (theo mặc định là true). Đối với response.redirect to work,

  1. Bộ đệm phải đúng,
  2. bạn không nên gửi thêm dữ liệu bằng cách sử dụng response.write vượt quá kích thước bộ đệm mặc định (trong trường hợp đó, nó sẽ tự tuôn ra khiến tiêu đề được gửi) do đó không cho phép bạn chuyển hướng.

1
Response.BufferOutput = true;trong Hành động, trong Bộ điều khiển?
Kiquenet

2

Sử dụng return RedirectPermanent(myUrl)hiệu quả cho tôi


Tôi có Hành động và Bộ điều khiển
Kiquenet

2

Bạn cũng có thể sử dụng mã được đề cập bên dưới

Response.Write("<script type='text/javascript'>"); Response.Write("window.location = '" + redirect url + "'</script>");Response.Flush();

1

Có một câu trả lời đơn giản cho điều này: Bạn đã được xuất một thứ gì đó khác, như văn bản hoặc bất kỳ thứ gì liên quan đến kết quả từ trang của bạn trước khi bạn gửi tiêu đề của mình. Điều này ảnh hưởng đến lý do tại sao bạn gặp lỗi đó.

Chỉ cần kiểm tra mã của bạn để biết đầu ra có thể tìm thấy hoặc bạn có thể đặt tiêu đề lên đầu phương pháp của mình để nó sẽ được gửi trước.


1

Nếu bạn đang cố gắng chuyển hướng sau khi tiêu đề đã được gửi (ví dụ: nếu bạn đang thực hiện chuyển hướng lỗi từ một trang được tạo một phần), bạn có thể gửi một số Javascript ứng dụng khách (location.replace hoặc location.href, v.v.) để chuyển hướng đến bất kỳ URL nào bạn muốn. Tất nhiên, điều đó phụ thuộc vào những gì HTML đã được gửi xuống.


1

Sự cố của tôi đã được giải quyết bằng cách thêm Trình xử lý ngoại lệ để xử lý "Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi". Lỗi này như được hiển thị bên dưới mã

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");}

1

Tôi đã giải quyết vấn đề bằng cách sử dụng: Response.RedirectToRoute ("CultureEnabled", RouteData.Values); thay vì Response.Redirect.


1

Lỗi Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi.

System.Web.HttpException (0x80004005): Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi.

Đề xuất

Nếu chúng tôi sử dụng asp.net mvc và làm việc trên cùng một bộ điều khiển và chuyển hướng đến các Hành động khác nhau thì bạn không cần phải viết ..
Response.Redirect ("ActionName", "ControllerName");
tốt hơn là chỉ sử dụng
return RedirectToAction ("Tên hành động");
hoặc
trả về View ("ViewName");


Tôi sử dụng ActionName từ ControllerName khác?
Kiquenet

0

Chức năng chuyển hướng có thể hoạt động bằng cách sử dụng tiêu đề http 'làm mới' (và có thể sử dụng mã 30X). Khi các tiêu đề đã được gửi đến máy khách, máy chủ sẽ không có cách nào để nối thêm lệnh chuyển hướng đó, đã quá muộn.


0

Nếu bạn nhận được Không thể chuyển hướng sau khi tiêu đề HTTP đã được gửi thì hãy thử mã bên dưới này.

HttpContext.Current.Server.ClearError();
// Response.Headers.Clear();
HttpContext.Current.Response.Redirect("/Home/Login",false);

0

Hãy chắc chắn rằng bạn không sử dụng Responsecác phương pháp của s 'như Response.Flush();trước phần chuyển hướng của bạn.


-3

Có 2 cách để sửa lỗi này:

  1. Chỉ cần thêm một returncâu lệnh sau của bạn Response.Redirect(someUrl); (nếu chữ ký phương thức không phải là "void", tất nhiên bạn sẽ phải trả về "loại" đó) như vậy:

    Response.Redirect ("Login.aspx");

    trở về;

Lưu ý rằng trả về cho phép máy chủ thực hiện chuyển hướng ... nếu không có nó, máy chủ muốn tiếp tục thực thi phần còn lại của mã của bạn ...

  1. Tạo Response.Redirect(someUrl)câu lệnh được thực thi CUỐI CÙNG của bạn trong phương thức ném ngoại lệ. Thay thế của bạn Response.Redirect(someUrl)bằng một chuỗi VARIABLE có tên "someUrl" và đặt nó thành vị trí chuyển hướng ... như sau:

//......some code

string someUrl = String.Empty

..... một số logic

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

...... thêm mã

// DI CHUYỂN Câu trả lời của bạn. Chuyển hướng đến ĐÂY (phần cuối của phương pháp):

Response.Redirect(someUrl);
return; 

xin lỗi nhưng điều này không có ý nghĩa gì đối với tôi. (Trong một phương thức trả về void) dư thừa returnphải làm gì? Các returnchỉ xác định rằng phương pháp này là hoàn thành. Nhưng khi không còn bất kỳ mã nào, phương pháp này vẫn hoàn tất. Và việc lưu trữ một url trong một biến không thay đổi bất cứ điều gì, ý tôi là: tại sao nên làm như vậy? Chuỗi cũng vậy. Điều đã biên dịch không tạo ra bất kỳ sự khác biệt nào giữa một chuỗi và một biến chứa một chuỗi ...: hãy nghĩ về x = 5, vì vậy x là 5 nhưng 5 cũng là 5. thậm chí 10/2 sẽ là 5 ... không có gì khác biệt
Matthias Burger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.