IIS7发送HTTP标头后,服务器无法设置状态

mar*_*inn 69 asp.net-mvc iis-7 http

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

  • 处理信息
    • 进程ID:3832
    • 进程名称:w3wp.exe
    • 帐户名称:NT AUTHORITY\NETWORK SERVICE
  • 例外信息
    • 异常类型:System.Web.HttpException
    • 异常消息:服务器无法在发送HTTP标头后设置状态.
  • 请求信息
    • 请求网址:http://www.myulr.pl/logon
    • 请求路径:/ logon
    • 用户主机地址:10.11.9.1
    • 用户:user001
    • 经过身份验证:是的
    • 身份验证类型:表单
    • 线程帐户名称: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) 
Run Code Online (Sandbox Code Playgroud)

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

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

ste*_*hbu 59

我会广泛同意Vagrant的原因:

  1. 您的操作正在执行,将标记写入响应流
  2. 流是无缓冲的,强制在标记写入开始之前写入响应头.
  3. 您的视图遇到运行时错误
  4. 异常处理程序试图将状态代码设置为非200的其他内容
  5. 因为标题已经发送而失败.

我不同意Vagrant的原因是"导致没有绑定错误"的补救措施 - 您仍然可能在View绑定中遇到运行时错误,例如null引用异常.

更好的解决方案是确保Response.BufferOutput = true;在将任何字节发送到Response流之前.例如,在您的控制器操作或应用程序中的On_Begin_Request.这样就可以设置服务器传输,cookie /头等,直到自然结束响应,或者调用结束/刷新.

当然还要检查缓冲区是否在堆栈中没有被刷新/设置为false.

MSDN参考: HttpResponse.BufferOutput


Dou*_*oug 45

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

Response.Redirect("/blah", true);
Run Code Online (Sandbox Code Playgroud)

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

return Redirect("/blah");
Run Code Online (Sandbox Code Playgroud)

  • 我有一个涉及.NET CAS客户端的类似问题,这个答案让我想到了我的问题.我本质上是回复"两次"响应,调用CasAuthentication.SingleSignOut(); 然后是RedirectToAction().显然这没有意义 - 你怎么能重定向两次,对吧?但我当时没有意识到这一点.我将LogOut操作返回类型从ActionResult更改为void,摆脱了重定向,问题解决了.谢谢! (2认同)

Vag*_*ant 15

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

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

解决方案是: 在生成任何内容之前,请检查是否存在任何错误.只有这样,当你确定没有问题时,你才能开始发送内容,比如标签.

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


Vah*_*idN 11

设置StatusCode然后Response.EndHandleUnauthorizedRequest方法中我有同样的问题AuthorizeAttribute

var ctx = filterContext.HttpContext;
ctx.Response.StatusCode = (int)HttpStatusCode.Forbidden;
ctx.Response.End();
Run Code Online (Sandbox Code Playgroud)

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

filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
Run Code Online (Sandbox Code Playgroud)

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


小智 10

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

if (!Response.IsRequestBeingRedirected)
{
   //do the redirect
}
Run Code Online (Sandbox Code Playgroud)