Сервер не может установить статус после отправки заголовков HTTP IIS7.5

Иногда я получаю исключение в моей рабочей среде:

  • Информация о процессе
    • Идентификатор процесса: 3832
    • Имя процесса: w3wp.exe
    • Имя учетной записи: NT AUTHORITY\NETWORK SERVICE
  • Информация об исключении
    • Тип исключения: System.Web.HttpException
    • Сообщение об исключении: Сервер не может установить статус после отправки HTTP-заголовков.
  • Запросить информацию
    • URL-адрес запроса: http://www.myulr.pl/logon
    • Путь запроса:/logon
    • Адрес хоста пользователя: 10.11.9.1
    • Пользователь: user001
    • Аутентифицировано: True
    • Тип аутентификации: формы
    • Имя учетной записи темы: NT AUTHORITY\NETWORK SERVICE
  • Информация о потоке
    • Идентификатор темы: 10
    • Имя учетной записи темы: NT AUTHORITY\NETWORK SERVICE
    • Выдает себя: False
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) 

Я не заметил эту ошибку в своей тестовой среде, что я должен проверить?

Я использую ASP.NET MVC 2 (Release Candidate 2)

Ответ 1

Я соглашусь с Вагрантом на причину:

  • ваше действие выполнялось, запись разметки в поток ответов
  • поток был небуферизованным, заставляя заголовки ответов записываться до начала написания разметки.
  • В вашем представлении возникла ошибка времени выполнения
  • Обработчик исключений запускает попытку установить код состояния на что-то еще не-200
  • Сбой, поскольку заголовки уже отправлены.

В тех случаях, когда я не согласен с Vagrant, это "причина отсутствия ошибок в привязке" - вы все равно можете столкнуться с ошибками во время выполнения в привязке вида, например. null ссылки исключений.

Лучшим решением для этого является обеспечение того, чтобы Response.BufferOutput = true; до того, как любые байты будут отправлены в поток Response. например в действии вашего контроллера или On_Begin_Request в приложении. Это позволяет устанавливать серверные передачи, файлы cookie/заголовки и т.д., Вплоть до естественного завершения ответа, или вызов end/flush.

Конечно, проверьте также, чтобы буфер не был сброшен/установлен в значение false еще ниже в стеке.

Ссылка MSDN: HttpResponse.BufferOutput

Ответ 2

Просто добавьте ответы выше. У меня была эта же проблема, когда я впервые начал использовать ASP.Net MVC, и я выполнял Response.Redirect во время действия контроллера:

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

Вместо того, чтобы возвращать действие Response.Redirect, я должен был возвращать RedirectAction:

return Redirect("/blah");

Ответ 3

HTTP-сервер не отправляет ответный ответ клиенту, пока вы не укажете ошибку или не начнете отправлять данные. Если вы начнете отправлять данные обратно клиенту, сервер сначала должен отправить ответную головку (которая содержит код состояния). После того, как заголовок был отправлен, вы больше не можете ставить код состояния в заголовке.

Здесь обычная проблема. Вы запускаете страницу и отправляете начальные теги (т.е. <head>). Затем сервер отправляет эти теги клиенту после первой отправки заголовка ответа HTTP с предполагаемым статусом SUCCESS. Теперь вы начинаете работать над мясом страницы и обнаруживаете проблему. Вы не можете отправить сообщение об ошибке в этот момент, потому что заголовок ответа, который будет содержать статус ошибки, уже отправлен.

Решение таково: Прежде чем создавать какой-либо контент вообще, проверьте, не возникнут ли какие-либо ошибки. Только тогда, когда вы заверили, что проблем не возникнет, можете ли вы начать отправку контента, например, тега.

В вашем случае, похоже, у вас есть страница входа в систему, которая обрабатывает запрос POST из формы. Вероятно, вы выбрасываете какой-то исходный HTML-код, а затем проверяете правильность имени пользователя и пароля. Вместо этого вы должны сначала аутентифицировать пользователя/пароль, прежде чем создавать какой-либо HTML вообще.

Ответ 4

У меня была такая же проблема с установкой StatusCode, а затем Response.End в HandleUnauthorizedRequest метод AuthorizeAttribute

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

Если вы используете .NET 4.5+, добавьте эту строку до Response.StatusCode

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

Если вы используете .NET 4.0, попробуйте SuppressFormsAuthenticationRedirectModule.

Ответ 5

Как проверить это перед выполнением перенаправления:

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

Ответ 6

На самом деле вы пытаетесь перенаправить страницу, на которую есть ответный запрос. Поэтому сначала вы сохраняете информацию, которую вы вбрасываете в буфер, используя response.buffer = true в начале страницы, а затем очищаете ее при необходимости с помощью response.flush эта ошибка будет исправлена.

Ответ 7

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

эхо "привет"; header ( "Местоположение: /fooobar.com/..." );

Простите меня и исправьте меня, если я ошибаюсь, но я все еще участвую в MS Technologies, и я пытался помочь.

Ответ 8

Прошу прощения, но я добавляю свои 2 цента в поток на всякий случай, если у кого-то такая же проблема.

  • Я использовал аутентификацию форм в своем приложении MVC
  • Но некоторые действия контроллера были "анонимными", то есть разрешены пользователям, не прошедшим проверку подлинности.
  • Иногда в этих действиях я все равно хочу, чтобы пользователи были перенаправлены на форму входа в каком-либо состоянии.
  • чтобы сделать это - у меня это в моем методе действий: return new HttpStatusCodeResult(401) - и ASP.NET очень приятно обнаружить это и перенаправляет пользователя на страницу входа! Магия, не так ли? Он даже имеет правильный параметр ReturnUrl и т.д.

Но вы видите, где я здесь? я возвращает 401. А ASP.NET перенаправляет пользователя. По существу, возвращается 302. Один код состояния заменяется другим.

И некоторые серверы IIS (только некоторые!) генерируют это исключение. Некоторые этого не делают. - У меня его нет на моем тестовом сервере, только на моем рабочем сервере (не всегда ли так правильно o_O)

Я знаю, что мой ответ по существу повторяет то, что уже сказано здесь, но иногда просто сложно понять, где именно происходит переписывание.

Ответ 9

Мы получили ту же ошибку - так что это может быть полезно для некоторых.

Для нас причина была очень простой. Изменение интерфейса смутило конечного пользователя, и он нажимал кнопку "Назад" в браузере в "плохое" время после отправки формы (конечно, мы должны были использовать шаблон PRG, но мы этого не сделали).

Мы исправили проблему, и пользователь больше не нажимает кнопку возврата. Задача решена.

Ответ 10

Если у кого-то все еще есть эта проблема. Попробуйте использовать вместо ovverriding

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

    }