Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 3: Server cannot append header after HTTP headers have been sent

We're busy upgrading an ASP.NET MVC 2 Application using the 3.5 framework to an ASP.NET MVC 3 Application running on the 4.0 framework.

There's a page which throws an exception when approached by using the browser back button. To support the browser back button on this page we implemented a system that requests the results for that page anew when arriving back on the page. I have no clear indications where to look for the problem however since I always only find the error

Server cannot append header after HTTP headers have been sent.

With stacktrace

at System.Web.HttpResponse.AppendHeader(String name, String value)
at System.Web.HttpResponseWrapper.AppendHeader(String name, String value)
at System.Web.Mvc.MvcHandler.AddVersionHeader(HttpContextBase httpContext)
at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<BeginProcessRequest>b__2()
at System.Web.Mvc.SecurityUtil.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust[TResult](Func`1 func)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

How come the HTTP headers already have been sent?

Thank you in advance, IvanL

EDIT: I am adding new information and insight I gained while hunting for this problem. The Asynch Controller mention of one of the answers got me wondering. When I found that I had to change the following for the old MVC2 method to work:

[HttpPost, ValidateInput(false)]
public void SearchResultOverview(SearchResultViewModel model, string searchUrl)
{
    if (!string.IsNullOrEmpty(searchUrl))
    {
        searchUrl = searchUrl.Replace("SearchPartial", "SearchPartialInternal");

        //NOTE MVC 3
        HttpContext.Server.TransferRequest(searchUrl, true);

        //NOTE MVC 2
        //System.Web.HttpContext.Current.RewritePath(searchUrl, false);

        //IHttpHandler httpHandler = new MvcHttpHandler();
        //// Process request
        //httpHandler.ProcessRequest(System.Web.HttpContext.Current);
    }
}

When I looked up the TransferRequest method I found that it Performs an asynchronous execution of the specified URL and preserves query string parameters. ( http://msdn.microsoft.com/en-us/library/system.web.httpserverutility.transferrequest.aspx )

Also there is an Exception being thrown before the exception I posted (I simply missed out on it since I cought the exception late). This exception is:

The SessionStateTempDataProvider class requires session state to be enabled.
   at System.Web.Mvc.SessionStateTempDataProvider.SaveTempData(ControllerContext controllerContext, IDictionary`2 values)
   at System.Web.Mvc.TempDataDictionary.Save(ControllerContext controllerContext, ITempDataProvider tempDataProvider)
   at System.Web.Mvc.Controller.PossiblySaveTempData()
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
   at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
   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.<>c__DisplayClasse.<EndProcessRequest>b__d()
   at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
   at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
   at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
   at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

So how do I make this work?

like image 228
IvanL Avatar asked Oct 10 '22 05:10

IvanL


2 Answers

Good news, today I solved my own problem after more thorough research on the cause of the exceptions. The first link that helped me understand what exactly might be the cause of my exceptions and errors was the following: http://www.eggheadcafe.com/tutorials/asp-net/79c73563-408a-493e-a369-d4b380bce549/aspnet-using-servertransferrequest.aspx

It details the workings of Server.TransferRequest and mentions the all important caveat: Session must be released by the main request before transferring to the child request. Digging deeper into how I would do this with MVC I came across the following post here on stackoverflow: How to simulate Server.Transfer in ASP.NET MVC?

This post in turn pointed me to an extremely important matter to know: throw new ApplicationException("TempData won't work with Server.TransferRequest!"); So I created the TransferResult class that can be found in that post and let the actions that required it return via that point. I found now that this exception was being hit in the specific cases I mentioned before. I myself never used TempData but apparently one of my colleagues did.

Due to the nature of the unimportant data inside I decided to Clear() the TempData before any Server.TransferRequest() which made my exceptions and problems melt like snow to the sun.

I want to thank all people that looked to solve this problem and am glad I can provide a closing conclusion and solution so it may benefit those that are looking at the same problem.

Sincerely, IvanL

like image 95
IvanL Avatar answered Oct 11 '22 20:10

IvanL


This can happen if buffering has been switched off on the page. Buffering means that asp.net waits for the whole request to be completed before sending the response. This means the header can be changed at any time. When buffering is off, the output is sent to the client as it's generated. You can't therefore change the headers at will, as they've already been sent.

From your stacktrace, it appears to be an async controller & I'm wondering if this has anything to do with it. I'm only guessing from what you've posted though.

Update

Correction, the async mention is actually framework code & nothing to do with your code. However from your code above, is SearchResultOverview an action on a controller? If so, then using the methods you are using to transfer execution is I think the cause of your problems.

It causing 2 mvchandlers to execute & they're interfering with each other. Routing would be a better way to redirect the request.

like image 22
Simon Halsey Avatar answered Oct 11 '22 20:10

Simon Halsey