ASP.NET MVC 3:服务器在发送HTTP标头后无法追加标头
我们正在忙于使用3.5框架将ASP.NET MVC 2应用程序升级到运行在4.0框架上的ASP.NET MVC 3应用程序。ASP.NET MVC 3:服务器在发送HTTP标头后无法追加标头
有一个页面在使用浏览器后退按钮接近时引发异常。为了支持此页面上的浏览器后退按钮,我们实现了一个系统,该页面返回时重新请求该页面的结果。我还没有明确的迹象表明在哪里寻找问题然而,由于我总是只发现错误
Server cannot append header after HTTP headers have been sent.
随着堆栈跟踪
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)
怎么会在HTTP标头已经被发送?
谢谢你在前进, IvanL
编辑: 我加入新的信息和见解,我获得了当寻找这个问题。异步控制器提到了其中一个答案让我想知道。当我发现我不得不改变旧MVC2方法如下工作:
[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);
}
}
当我抬头看TransferRequest方法我发现它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)
也有一个例外是在我发布的例外之前抛出(我只是错过了它,因为我迟到了这个例外)。这个例外是:
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)
那么我该怎么做这项工作?
好消息,今天我就例外的原因更深入的研究后解决我自己的问题。第一个链接,帮助我了解究竟是什么可能是我的例外和错误的原因是:http://www.eggheadcafe.com/tutorials/asp-net/79c73563-408a-493e-a369-d4b380bce549/aspnet-using-servertransferrequest.aspx
它详细介绍了Server.TransferRequest的工作原理并提到了所有重要的警告:会话必须由主要请求释放在转移到子请求之前。更仔细地分析我将如何做到这一点与MVC我碰到下面的帖子在这里来了计算器:How to simulate Server.Transfer in ASP.NET MVC?
这篇文章反过来向我指出一个非常重要的事情知道:throw new ApplicationException("TempData won't work with Server.TransferRequest!");
所以我创建了一个可以找到TransferResult类在那篇文章中,让那些需要它的操作通过这一点返回。现在我发现这个例外在我之前提到的具体案例中受到了打击。我自己从来没有使用TempData,但显然我的一个同事做到了。
由于内部不重要的数据的性质,我决定在Server.TransferRequest()
之前决定使用Clear()
的TempData,这使得我的例外和问题像雪一样融化成太阳。
我想感谢所有希望解决这个问题的人,我很高兴能提供一个结论性的结论和解决方案,因此它可能有利于那些看到相同问题的人。
真诚,IvanL
如果页面上的缓冲关闭,可能会发生这种情况。缓冲意味着asp.net在发送响应之前等待整个请求完成。这意味着标题可以随时更改。当缓冲关闭时,输出在生成时发送到客户端。因此,您不能随意更改标题,因为它们已经发送。
从你的stacktrace,它似乎是一个异步控制器&我想知道这是否有什么关系。我只是从你发布的内容中猜测出来的。
更新
修正,异步提实际上是框架代码&无关,与你的代码。但是从你上面的代码,在控制器上的操作是SearchResultOverview
?如果是这样,那么使用你用来传递执行的方法是我认为你的问题的原因。
它导致2 mvchandlers执行&他们互相干扰。路由将是重定向请求的更好方式。
我记得前段时间有这个问题。我不记得确切的条件,但它与直接在自定义操作过滤器中设置标题和http状态代码有关。
当时我的目标是在用户身份验证超时并单击ajax操作链接时显示自定义页面/消息(例如,当他离开页面打开一段时间后,他回来并单击链接) ,所以asp.net mvc没有显示div内的默认登录页面(很丑陋)。我没有手头上的代码的权利,但它是这样的:
public class AjaxFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.AddHeader("name", "value");
filterContext.HttpContext.Response.StatusCode = 200;
filterContext.Result = something;
}
base.OnActionExecuting(filterContext);
}
}
是,在asp.net的MVC的早期版本尝试相同的代码给我的东西“不能追加头“错误。我不记得我是如何解决这个问题的,但是这并不容易。如果您认为这种情况适用于您,我可以通过旧项目搜索固定代码。
希望它可以帮助
嗯,让我看看,如果我可以推断出这个psychicly ... ... ...呃..没了..你将不得不提供一些代码。什么标题你追加,什么时候? – 2011-12-14 17:42:35
也许这将帮助: http://stackoverflow.com/questions/2383169/server-cannot-set-status-after-http-headers-have-been-sent-iis7-5 – 2011-12-14 17:46:43
@Mystere人:这就是要点。我不是自己添加任何头文件,似乎从MVC2更改为MVC3创建此问题,因为代码运行良好,没有任何MVC2例外。如果你看一下堆栈跟踪,你会发现:`在System.Web.Mvc.MvcHandler.AddVersionHeader(HttpContextBase httpContext)`这意味着MVC本身试图添加一个头,但它不能。 我确实试过了你用`reponse.BufferOutput = true`连接了我的问题的解决方案,但它不起作用。我总是收到这个异常和堆栈跟踪。 – IvanL 2011-12-15 09:33:22