71

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
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)

Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
marcinn
  • 1,679
  • 2
  • 21
  • 44
  • This is happening to me too. The error is coming from within the HandleErrorAttribute, as in your case. – Gabe Moothart Apr 08 '10 at 15:19
  • 1
    Were you able to solve this problem? – Azho KG May 15 '10 at 15:43
  • 3
    I've had the same issue since switching to MVC 2. Also when setting cookies, similar error -- can't happen after headers have been sent. I am curious about the answer. In my case, switching between http/https seems to play a part. – Matt Sherman May 20 '10 at 01:08
  • 3
    I found that I was trying to redirect user in Actionfilter (OnActionExecuting) - this was a problem – marcinn Jun 03 '11 at 10:53

10 Answers10

62

I'll broadly agree with Vagrant on the cause:

  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.

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.

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.

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

MSDN Reference: HttpResponse.BufferOutput

stephbu
  • 5,011
  • 24
  • 40
  • 1
    I get the same error but in my case it happens when I try to call a child action. I tried setting `Response.BufferOutput = true` at the beginning of the parent action but this didn't help. Any ideas? – Samo Feb 18 '11 at 16:30
  • Samo, somewhere earlier in your code something is writing bytes to the response stream, set buffering mu at the beginning of request processing e.g. before you let your Action begin in your controller. – stephbu Feb 20 '11 at 01:49
  • How use `HttpResponse.BufferOutput` in MVC Controller ? – Kiquenet Mar 14 '19 at 14:53
  • In my Index Action Controller i have : `[HttpPost]` and `[ValidateAntiForgeryToken]` – Kiquenet Mar 14 '19 at 15:34
  • (Assuming you're talking about System.Web.Mvc.Controller) Controller carries a Response accessor to give access to the HttpResponse object for the current HTTP request context. Such that in controller methods the following is valid: `this.Response.BufferOutput` – stephbu Mar 15 '19 at 14:11
51

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:

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

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

return Redirect("/blah");
Doug
  • 6,390
  • 4
  • 54
  • 81
  • 1
    Thanks, i was doing the same in my filter. Changed it and this got fixed... //Url helper to generate redirect url. UrlHelper urlHelper = new UrlHelper(filterContext.RequestContext); filterContext.Result = new RedirectResult(urlHelper.Action(ActionNames.Index, ControllerNames.CustomerSearch, new{Area = ""})); //at the end base.OnActionExecuting(filterContext); – learning... Apr 24 '12 at 14:12
  • 2
    I had a similar issue involving the .NET CAS Client and this answer clued me into my problem. I was essentially returning a response 'twice', calling CasAuthentication.SingleSignOut(); followed by a RedirectToAction(). Obviously this doesn't make sense -- how can you redirect twice, right? But I didn't realize it at the time. I changed my LogOut action return type from ActionResult to void, got rid of the Redirect, and the problem was solved. Thanks! – Pandincus Aug 16 '12 at 20:16
16

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.

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.

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 any HTML at all.

quirkystack
  • 1,267
  • 2
  • 16
  • 42
Vagrant
  • 1,678
  • 12
  • 19
11

I had the same issue with setting StatusCode and then Response.End in HandleUnauthorizedRequest method of 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

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;

If you are using .NET 4.0, try SuppressFormsAuthenticationRedirectModule.

VahidN
  • 16,098
  • 7
  • 63
  • 110
11

How about checking this before doing the redirect:

if (!Response.IsRequestBeingRedirected)
{
   //do the redirect
}
Sandeep
  • 111
  • 1
  • 2
3

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 = true in beginning of the page and then flush it when required using response.flush this error will get fixed

Tim Cooper
  • 144,163
  • 35
  • 302
  • 261
hema
  • 31
  • 1
1

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.:

echo "hello"; header("Location: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.

Adil Mehmood
  • 464
  • 3
  • 13
1

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

  • 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 still want 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 ReturnUrl parameter etc.

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.

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)

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.

jazzcat
  • 4,051
  • 3
  • 30
  • 34
1

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).

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

niico
  • 8,315
  • 18
  • 65
  • 125
0

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

    }
Emre
  • 83
  • 2
  • 9