asp.net-mvc IIS7.5 发送 HTTP 标头后,服务器无法设置状态

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2383169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 00:10:42  来源:igfitidea点击:

Server cannot set status after HTTP headers have been sent IIS7.5

asp.net-mvchttpiis-7

提问by marcinn

Sometimes I get exception in my production environment:

有时我在生产环境中遇到异常:

  • Process information
    • Process ID: 3832
    • Process name: w3wp.exe
    • Account name: NT AUTHORITY\NETWORK SERVICE
  • Exception information
    • Exception type: System.Web.HttpException
    • Exception message: Server cannot set status after HTTP headers have been sent.
  • Request information
    • Request URL: http://www.myulr.pl/logon
    • Request path: /logon
    • User host address: 10.11.9.1
    • User: user001
    • Is authenticated: True
    • Authentication Type: Forms
    • Thread account name: NT AUTHORITY\NETWORK SERVICE
  • Thread information
    • Thread ID: 10
    • Thread account name: NT AUTHORITY\NETWORK SERVICE
    • Is impersonating: False
  • 处理信息
    • 进程 ID:3832
    • 进程名称:w3wp.exe
    • 帐户名称:NT AUTHORITY\NETWORK SERVICE
  • 异常信息
    • 异常类型:System.Web.HttpException
    • 异常消息:发送 HTTP 标头后,服务器无法设置状态。
  • 索取资料
    • 请求网址:http: //www.myulr.pl/logon
    • 请求路径:/logon
    • 用户主机地址:10.11.9.1
    • 用户:user001
    • 是否经过身份验证:True
    • 身份验证类型:表单
    • 线程帐户名:NT AUTHORITY\NETWORK SERVICE
  • 线程信息
    • 线程 ID:10
    • 线程帐户名:NT AUTHORITY\NETWORK SERVICE
    • 冒充:假
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) 

I didn't noticed this error on my test environment what should I check?

我在测试环境中没有注意到这个错误,我应该检查什么?

I am using ASP.NET MVC 2 (Release Candidate 2)

我正在使用 ASP.NET MVC 2(发布候选 2)

采纳答案by stephbu

I'll broadly agree with Vagrant on the cause:

我会大致同意 Vagrant 的原因:

  1. your action was executing, writing markup to response stream
  2. the stream was unbuffered forcing the response headers to get written before the markup writing could begin.
  3. Your view encountered a runtime error
  4. Exception handler kicks in trying to set the status code to something else non-200
  5. Fails because the headers have already been sent.
  1. 您的操作正在执行,将标记写入响应流
  2. 流是无缓冲的,强制在标记写入开始之前写入响应标头。
  3. 您的视图遇到运行时错误
  4. 异常处理程序开始尝试将状态代码设置为非 200 的其他内容
  5. 失败,因为标头已经发送。

Where I disagree with Vagrant is the "cause no errors in binding" remedy - you could still encounter runtime errors in View binding e.g. null reference exceptions.

我不同意 Vagrant 的地方是“导致绑定中没有错误”的补救措施 - 您仍然可能会在视图绑定中遇到运行时错误,例如空引用异常。

A better solution for this is to ensure that Response.BufferOutput = true;before any bytes are sent to the Response stream. e.g. in your controller action or On_Begin_Request in application. This enables server transfers, cookies/headers to be set etc. right the way up to naturally ending response, or calling end/flush.

对此更好的解决方案是确保Response.BufferOutput = true;在将任何字节发送到响应流之前。例如在您的控制器操作或应用程序中的 On_Begin_Request 中。这使得服务器传输、cookies/headers 设置等一直到自然结束响应,或调用 end/flush。

Of course also check that buffer isn't being flushed/set to false further down in the stack too.

当然,还要检查缓冲区是否也没有在堆栈中进一步刷新/设置为 false。

MSDN Reference: HttpResponse.BufferOutput

MSDN 参考: HttpResponse.BufferOutput

回答by Doug

Just to add to the responses above. I had this same issue when i first started using ASP.Net MVC and i was doing a Response.Redirect during a controller action:

只是为了补充上面的回答。当我第一次开始使用 ASP.Net MVC 并且我在控制器操作期间执行 Response.Redirect 时,我遇到了同样的问题:

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

Instead of returning a Response.Redirectaction i should have been returning a RedirectAction:

而不是返回一个Response.Redirect动作,我应该返回一个RedirectAction

return Redirect("/blah");

回答by Vagrant

The HTTP server doesn't send the response header back to the client until you either specify an error or else you start sending data. If you start sending data back to the client, then the server has to send the response head (which contains the status code) first. Once the header has been sent, you can no longer put a status code in the header, obviously.

在您指定错误或开始发送数据之前,HTTP 服务器不会将响应标头发送回客户端。如果您开始将数据发送回客户端,则服务器必须首先发送响应头(其中包含状态代码)。显然,一旦发送了标头,就不能再在标头中放置状态代码。

Here's the usual problem. You start up the page, and send some initial tags (i.e. <head>). The server then sends those tags to the client, after first sending the HTTP response header with an assumed SUCCESS status. Now you start working on the meat of the page and discover a problem. You can not send an error at this point because the response header, which would contain the error status, has already been sent.

这是通常的问题。您启动页面,并发送一些初始标签(即<head>)。在首先发送具有假定成功状态的 HTTP 响应标头之后,服务器然后将这些标签发送到客户端。现在您开始处理页面的内容并发现一个问题。此时您不能发送错误,因为包含错误状态的响应标头已经发送。

The solution is this:Before you generate any content at all, check if there are going to be any errors. Only then, when you have assured that there will be no problems, can you then start sending content, like the tag.

解决方案是这样的:在生成任何内容之前,检查是否会有任何错误。只有这样,当您确定不会出现问题时,您才能开始发送内容,例如标签。

In your case, it seems like you have a login page that processes a POST request from a form. You probably throw out some initial HTML, then check if the username and password are valid. Instead, you should authenticate the user/password first, before you generate anyHTML at all.

在您的情况下,您似乎有一个处理来自表单的 POST 请求的登录页面。您可能会丢弃一些初始 HTML,然后检查用户名和密码是否有效。相反,您应该先验证用户/密码,然后再生成任何HTML。

回答by VahidN

I had the same issue with setting StatusCodeand then Response.Endin HandleUnauthorizedRequestmethod of AuthorizeAttribute

我在设置时遇到了同样的问题,StatusCode然后Response.EndHandleUnauthorizedRequest方法中AuthorizeAttribute

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

If you are using .NET 4.5+, add this line before Response.StatusCode

如果您使用的是 .NET 4.5+,请在此之前添加此行 Response.StatusCode

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

If you are using .NET 4.0, try SuppressFormsAuthenticationRedirectModule.

如果您使用的是 .NET 4.0,请尝试SuppressFormsAuthenticationRedirectModule

回答by Sandeep

How about checking this before doing the redirect:

在进行重定向之前检查一下如何:

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

回答by hema

You are actually trying to redirect a page which has some response to throw. So first you keep the information you have throw in a buffer using response.buffer = truein beginning of the page and then flush it when required using response.flushthis error will get fixed

您实际上是在尝试重定向一个有一些响应要抛出的页面。因此,首先您将在response.buffer = true页面开头使用的信息保留在缓冲区中,然后在需要时使用response.flush此错误将其刷新

回答by Adil Mehmood

I remember the part from this exception : "Cannot modify header information - headers already sent by" occurring in PHP. It occurred when the headers were already sent in the redirection phase and any other output was generated e.g.:

我记得这个异常中的部分:“无法修改标题信息 - 标题已经发送”在 PHP 中发生。当在重定向阶段已经发送了标头并且生成了任何其他输出时,就会发生这种情况,例如:

echo "hello"; header("Location:http://stackoverflow.com");

echo "你好"; header("位置:http: //stackoverflow.com");

Pardon me and do correct me if I am wrong but I am still learning MS Technologies and I was trying to help.

请原谅我,如果我错了,请纠正我,但我仍在学习 MS 技术,我正在努力提供帮助。

回答by niico

We were getting the same error - so this may be useful to some.

我们遇到了同样的错误 - 所以这可能对某些人有用。

For us the cause was super simple. An interface change confused an end user and they were pressing the back button in the browser at a 'bad' time after a form submission (sure we should probably have used a PRG pattern, but we didn't).

对我们来说,原因非常简单。界面更改使最终用户感到困惑,他们在提交表单后的“糟糕”时间按下了浏览器中的后退按钮(当然我们应该使用 PRG 模式,但我们没有)。

We fixed the issue and the user is no longer pressing the back button. Problem solved.

我们解决了这个问题,用户不再按后退按钮。问题解决了。

回答by jazzcat

I apologize, but I'm adding my 2 cents to the thread just in case anyone has the same problem.

我很抱歉,但我将我的 2 美分添加到线程中,以防万一有人遇到同样的问题。

  • I used Forms Authentication in my MVC app
  • But some controller-actions were "anonymous" i.e. allowed to non-authenticated users
  • Sometimes in those actions I would stillwant users to be redirected to the login form under some condition
  • to do that - I have this in my action method: return new HttpStatusCodeResult(401)- and ASP.NET is super nice to detect this, and it redirects the user to the login page! Magic, right? It even has the proper ReturnUrlparameter etc.
  • 我在我的 MVC 应用程序中使用了表单身份验证
  • 但是一些控制器操作是“匿名的”,即允许未经身份验证的用户
  • 有时在这些操作中,我仍然希望用户在某些情况下被重定向到登录表单
  • 要做到这一点 - 我在我的操作方法中有这个:return new HttpStatusCodeResult(401)- ASP.NET 非常好地检测到这一点,它将用户重定向到登录页面!魔法,对吧?它甚至有适当的ReturnUrl参数等。

But you see where I'm getting here? I return 401. And ASP.NET redirects the user. Which is essentially returns 302. One status code is replaced with another.

但是你看到我要到哪里了吗?我返回 401。并且 ASP.NET 重定向用户。这本质上是返回 302。一个状态代码被另一个替换。

And some IIS servers (just some!) throw this exception. Some don't. - I don't have it on my test serevr, only on my production server (ain't it always the case right o_O)

一些 IIS 服务器(只是一些!)抛出这个异常。有些没有。- 我的测试服务器上没有它,只有在我的生产服务器上(是不是总是这样 o_O)

I know my answer is essentially repeating what's already said here, but sometimes it's just hard to figure out where this overwriting happens exactly.

我知道我的回答基本上是重复这里已经说过的内容,但有时很难弄清楚这种覆盖究竟发生在哪里。

回答by Emre

?f someone still having this problem.Try to use instead of 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" } });
        }

    }