Server cannot set status after HTTP headers have been sent IIS7.5
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)
Solution 1:
I'll broadly agree with Vagrant on the cause:
- your action was executing, writing markup to response stream
- the stream was unbuffered forcing the response headers to get written before the markup writing could begin.
- Your view encountered a runtime error
- Exception handler kicks in trying to set the status code to something else non-200
- 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
Solution 2:
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");
Solution 3:
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.
Solution 4:
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.
Solution 5:
How about checking this before doing the redirect:
if (!Response.IsRequestBeingRedirected)
{
//do the redirect
}