Почему я получаю сообщение «Невозможно выполнить перенаправление после отправки заголовков HTTP» при вызове Response.Redirect ()?

85

Когда я звоню, Response.Redirect(someUrl)я получаю следующее исключение HttpException:

Невозможно перенаправить после отправки заголовков HTTP.

Почему я это получаю? И как я могу исправить эту проблему?

Сэмюэл Мичем
источник

Ответы:

121

Согласно документации MSDN для Response.Redirect(string url), он будет генерировать исключение HttpException, когда «выполняется попытка перенаправления после отправки заголовков HTTP». Поскольку Response.Redirect(string url)используется заголовок ответа Http «Местоположение» ( http://en.wikipedia.org/wiki/HTTP_headers#Responses ), его вызов приведет к отправке заголовков клиенту. Это означает, что если вы вызовете его во второй раз или вызовете его после того, как заголовки будут отправлены другим способом, вы получите исключение HttpException.

Один из способов защитить себя от многократного вызова Response.Redirect () - проверить Response.IsRequestBeingRedirectedсвойство (bool) перед его вызовом.

// 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
Ага точно. Это происходит довольно легко с ASP.NET MVC 4 и фильтрами исключений и т. Д. Вы также не можете изменить код состояния ответа HTTP после того, как было выполнено перенаправление 301/302.
Jaans 04
Я решил проблему, сделав все свойства на моей странице «статическими»
Сал
4
сделать ваши свойства статичными - опасное решение
изыскатель
Как можно вызвать перенаправление во второй раз, если исключение ThreadAbortException (с первого раза) не будет обнаружено? :} «Вызов Redirect эквивалентен вызову Redirect со вторым параметром ( endResponse), установленным в true».
user2864740 08
1
Это странно, но в устаревшем приложении веб-форм Response.IsRequestBeingRedirectedэто ложь, и я все еще получаю то же исключение ( Application_EndRequestметод внутреннего события в Global.asax). Не понимаю почему.
Алиссон
17

Как только вы отправляете какой-либо контент клиенту, заголовки HTTP уже отправлены. Response.Redirect()Вызов работает, посылая специальную информацию в заголовках , которые делают браузер попросить другой URL.

Поскольку заголовки уже были отправлены, asp.net не может делать то, что вы хотите (изменять заголовки)

Вы можете обойти это, а) либо выполняя перенаправление, прежде чем делать что-либо еще, либо б) попробовать использовать, Response.Buffer = trueпрежде чем делать что-либо еще, чтобы убедиться, что никакие выходные данные не отправляются клиенту до тех пор, пока не будет выполнена вся страница.

Филип Рик
источник
Для меня это не работает. Я использую .NET, MVC, и у меня есть вызов внутри метода контроллера. Я все еще получаю исключение, хотя происходит перенаправление.
FrenkyB
8

Перенаправление может произойти только в том случае, если первая строка в HTTP-сообщении - " HTTP/1.x 3xx Redirect Reason".

Если вы уже позвонили Response.Write()или установили какие-то заголовки, будет слишком поздно для перенаправления. Вы можете попробовать позвонить Response.Headers.Clear()перед перенаправлением, чтобы узнать, поможет ли это.

Марк Сидаде
источник
Я использую return RedirectToAction("Logout", "Authentication");и получаю эту ошибку
Kiquenet
Когда я попытался очистить заголовки, я получил System.PlatformNotSupportedException: для этой операции требуется интегрированный режим конвейера IIS.
IrishChieftain
3

Просто проверьте, не установлено ли для параметра буферизации значение false (по умолчанию - true). Чтобы response.redirect работал,

  1. Буферизация должна быть верной,
  2. вам не следовало отправлять больше данных с помощью response.write, размер которого превышает размер буфера по умолчанию (в этом случае он будет сброшен, что приведет к отправке заголовков), поэтому вы не сможете перенаправить.

источник
1
Response.BufferOutput = true;в действии, в контроллере?
Kiquenet
2

Использование return RedirectPermanent(myUrl)сработало для меня

Василис
источник
У меня есть действие и контроллер
Kiquenet
2

Вы также можете использовать указанный ниже код

Response.Write("<script type='text/javascript'>"); Response.Write("window.location = '" + redirect url + "'</script>");Response.Flush();
Дипанки Джадав
источник
1

На это есть один простой ответ: вы выводили что-то еще, например текст или что-то, что связано с выводом с вашей страницы, прежде чем вы отправите свой заголовок. Это влияет на то, почему вы получаете эту ошибку.

Просто проверьте свой код на возможный вывод, или вы можете поместить заголовок поверх своего метода, чтобы он был отправлен первым.

ДыкDigital
источник
1

Если вы пытаетесь перенаправить после отправки заголовков (если, например, вы выполняете перенаправление с ошибкой с частично сгенерированной страницы), вы можете отправить некоторый клиентский Javascript (location.replace или location.href и т. Д.) для перенаправления на любой URL-адрес, который вы хотите. Конечно, это зависит от того, какой HTML уже отправлен.

Брэд
источник
1

Моя проблема была решена путем добавления обработчика исключений для обработки сообщения «Невозможно перенаправить после отправки заголовков HTTP». эта ошибка, как показано ниже, код

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
источник
1

Я решил проблему с помощью: Response.RedirectToRoute ("CultureEnabled", RouteData.Values); вместо Response.Redirect.

утилит
источник
1

Ошибка Не удается выполнить перенаправление после отправки заголовков HTTP.

System.Web.HttpException (0x80004005): невозможно выполнить перенаправление после отправки заголовков HTTP.

Предложение.

Если мы используем asp.net mvc и работаем на одном контроллере и перенаправляем на другое действие, вам не нужно писать ..
Response.Redirect ("ActionName", "ControllerName");
лучше использовать только
return RedirectToAction ("ActionName");
или
верните View ("ViewName");

Рам Самудж
источник
Я использую ActionName из другого ControllerName?
Kiquenet
0

Функция перенаправления, вероятно, работает с использованием HTTP-заголовка «обновить» (а также, возможно, с использованием кода 30X). После того, как заголовки были отправлены клиенту, сервер не может добавить эту команду перенаправления, уже слишком поздно.

Натан
источник
0

Если вы получаете сообщение «Невозможно перенаправить» после отправки заголовков HTTP, попробуйте следующий код.

HttpContext.Current.Server.ClearError();
// Response.Headers.Clear();
HttpContext.Current.Response.Redirect("/Home/Login",false);
Аашиш Гарг
источник
0

Убедитесь, что вы не используете Responseметоды s, как Response.Flush();перед перенаправляющей частью.

1_bug
источник
-3

Есть 2 способа исправить это:

  1. Просто добавьте returnоператор после вашего Response.Redirect(someUrl); (если подпись метода не «недействительна», вам, конечно, придется вернуть этот «тип») следующим образом:

    Response.Redirect ("Login.aspx");

    возвращение;

Обратите внимание, что return позволяет серверу выполнить перенаправление ... без него сервер хочет продолжить выполнение остальной части вашего кода ...

  1. Сделайте ваш Response.Redirect(someUrl)ПОСЛЕДНИЙ выполненный оператор в методе, вызывающем исключение. Замените your Response.Redirect(someUrl)строкой VARIABLE с именем «someUrl» и установите ее в место перенаправления ... следующим образом:

//......some code

string someUrl = String.Empty

..... немного логики

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

...... больше кода

// ПЕРЕМЕСТИТЕ свой ответ. Перенаправьте ЗДЕСЬ (конец метода):

Response.Redirect(someUrl);
return; 
user9150083
источник
извините, но для меня это не имеет никакого смысла. Что должен делать (в методе с возвратом пустоты) этот избыточный return? returnТолько определяет , что метод завершается. Но когда кода не остается, метод все равно завершается. И сохранение URL-адреса в переменной ничего не меняет, я имею в виду: зачем это нужно? Строка такая же. Скомпилированная вещь не имеет никакого значения между строкой и переменной, содержащей строку ...: подумайте x = 5, так что x равно 5, но 5 также равно 5. даже 10/2 будет 5 ... тоже не имеет значения
Маттиас Бургер