【问题标题】:IIS7 Overrides customErrors when setting Response.StatusCode?IIS7 在设置 Response.StatusCode 时覆盖 customErrors?
【发布时间】:2010-09-30 20:39:55
【问题描述】:

这里有一个奇怪的问题。每个人都知道,如果您使用 web.config 的 customErrors 部分来制作自定义错误页面,您应该将您的 Response.StatusCode 设置为适当的值。例如,如果我制作了一个自定义的 404 页面并将其命名为 404.aspx,我可以将 <% Response.StatusCode = 404 %> 放入内容中,以使其具有真正的 404 状态标题。

一直跟着我?好的。现在尝试在 IIS7 上执行此操作。我无法让它工作,期间。如果在自定义错误页面中设置了Response.StatusCode,IIS7 似乎会完全覆盖自定义错误页面,并显示自己的状态页面(如果您已配置)。

有没有其他人看到过这种行为并且可能知道如何解决它?它在 IIS6 下工作,所以我不知道为什么会发生变化。

注意:这与ASP.NET Custom 404 Returning 200 OK Instead of 404 Not Found中的问题不同

【问题讨论】:

  • Bobby,我实际上发现了这个问题并尝试了它,但它并没有解决问题。不过谢谢。
  • 我想评论一下,从 Classic 切换到 Integrated pipeine 时也会出现此问题。我使用了@PavelChuchuva 解决方案(@RickStrahl 解决方案也可以)。我猜经典中的“直通”是自动的,在集成中它需要服务器的全局错误页面处理..

标签: asp.net iis-7


【解决方案1】:

在 system.webServer/httpErrors 部分中将现有响应设置为 PassThrough:

  <system.webServer>
    <httpErrors existingResponse="PassThrough" />
  </system.webServer>

existingResponse 属性的默认值为 Auto:

Auto 告诉自定义错误模块做正确的事情。客户端看到的实际错误文本将受到影响,具体取决于IHttpResponse::GetStatus 调用中返回的 fTrySkipCustomErrors 的值。当 fTrySkipCustomErrors 设置为 true 时,自定义错误模块会让响应通过,但如果设置为 false,自定义错误模块会用自己的文本替换文本。

更多信息:What to expect from IIS7 custom error module

【讨论】:

  • 请注意,将 existingResponse 设置为 PassThrough 可能会导致一些副作用。请在任何更改之前掌握 Pavel 提供的链接。
  • &lt;httpErrors existingResponse="PassThrough" /&gt; 是否等同于 Response.TrySkipIisCustomErrors 还是它们的行为不同?
  • @sbjornu 他们实现了相同的功能,但使用Response.TrySkipIisCustomErrors,您可以更好地控制何时显示 IIS 自定义错误。
  • 谢谢,我看到了很多关于 response.tryskipiiscustomerrors 的信息,但对现有的响应没有那么多。
  • 尽管如此,我们有 HttpContext.Current.Response.TrySkipIisCustomErrors = true;但这没有用。但是这解决了我的问题。
【解决方案2】:

使行为一致的最简单方法是清除错误并使用Response.TrySkipIisCustomErrors 并将其设置为true。这将覆盖页面内的 IIS 全局错误页面处理或 Application_Error 中的全局错误处理程序。

Server.ClearError();
Response.TrySkipIisCustomErrors = true;

通常,您应该在处理应用程序错误处理程序未捕获的所有错误的 Application_Error 处理程序中执行此操作。

更详细的信息可以在这篇博文中找到: http://www.west-wind.com/weblog/posts/745738.aspx

【讨论】:

  • 这对我也不起作用(IIS8),并且建议似乎与 OP 不匹配(假设我阅读正确)。我想要在 Web.config 中配置的 customError 触发。使用Response.TrySkipIisCustomErrors = true 我得到相同的行为:显示丑陋的服务器生成的错误页面。将其设置为 false 什么都不会发生 - 一个空白的浏览器窗口。
  • 对我来说工作得很好!虽然 Pavel Chuchuva 在他的回答中提到的设置也有效,但它有一些副作用,导致了其他问题。此设置让我可以在我想要的特定场景中跳过 IIS 错误覆盖,同时保持其他所有行为不变。
  • 对我来说在 Azure 中运行良好。服务器头Server:Microsoft-IIS/8.5 X-AspNet-Version:4.0.30319 X-AspNetMvc-Version:5.2 X-Powered-By:ASP.NET
  • 我仍然发现我需要设置 customErrors mode="Off" 才能使其正常工作。如果我这样做,那么当我在这个答案中使用代码时,httpErrors existingResponse="Auto"(默认值)对我来说可以正常工作。
【解决方案3】:

已解决: 事实证明,需要打开“详细错误”才能让 IIS7 “通过”您可能遇到的任何错误页面。见http://forums.iis.net/t/1146653.aspx

【讨论】:

  • 虽然这篇文章被标记为答案,但我认为值得花时间阅读其他回复以获取有关该主题的更多见解。
  • 删除也可以。 FilterConfig 中的 HandleErrorAttribute
【解决方案4】:

我不确定这在本质上是否相似,但我解决了一个表面上听起来相似的问题,这就是我的处理方式。

首先,existingResponse (Auto) 的默认值在我的情况下是正确的答案,因为我有自定义的 404、400 和 500(我可以创建其他值,但这三个足以满足我正在做的事情)。以下是对我有帮助的相关部分。

来自 web.config:

<customErrors mode="Off" />

<httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
  <clear />
  <error statusCode="404" path="/errors/404.aspx" responseMode="ExecuteURL" />
  <error statusCode="500" path="/errors/500.aspx" responseMode="ExecuteURL" />
  <error statusCode="400" path="/errors/400.aspx" responseMode="ExecuteURL" />
</httpErrors>

从那里,我将它添加到 global.asax 上的 Application_Error 中:

    Response.TrySkipIisCustomErrors = True

在我的每个自定义错误页面上,我都必须包含正确的响应状态代码。就我而言,我使用自定义 404 将用户发送到我网站的不同部分,因此我希望返回 404 状态代码,除非它实际上是死页。

不管怎样,我就是这样做的。希望对某人有所帮助。

【讨论】:

    【解决方案5】:

    这个问题一直令人头疼。前面提到的任何建议都没有单独为我解决它,所以我将我的解决方案包括在内。作为记录,我们的环境/平台使用:

    • .NET 框架 4
    • MVC 3
    • IIS8(工作站)和 IIS7(Web 服务器)

    具体来说,我试图获得一个 HTTP 404 响应,它将用户重定向到我们的自定义 404 页面(通过 Web.config 设置)。

    首先,我的代码必须抛出一个HttpException。从控制器返回 NotFoundResult 并没有达到我想要的结果。

    throw new HttpException(404, "There is no class with that subject");
    

    然后我必须在 Web.config 中配置 两个 customErrorshttpError 节点。

    <customErrors mode="On" defaultRedirect="/classes/Error.aspx">
      <error statusCode="404" redirect="/classes/404.html" />
    </customErrors>
    

    ...

    <httpErrors errorMode="Custom" existingResponse="Auto" defaultResponseMode="ExecuteURL">
      <clear />
      <error statusCode="404" path="/classes/404.aspx" responseMode="ExecuteURL" />
    </httpErrors>
    

    请注意,我将existingResponse 保留为Auto,这与@sefl 提供的解决方案不同。

    customErrors 设置似乎是处理我明确抛出的HttpException 所必需的,而httpErrors 节点处理不在 Globals.asax.cs 中指定的路由模式的 URL。

    附:使用这些设置我不需要设置Response.TrySkipIisCustomErrors

    【讨论】:

      【解决方案6】:

      TrySkipIisCustomErrors 只是谜题的一部分。如果您使用自定义错误页面,但您还想提供一些基于 4xx 状态的 RESTful 内容,那么您就有问题了。将 web.config 的 httpErrors.existingResponse 设置为“Auto”不起作用,因为 .net 似乎总是向 IIS 提供一些页面内容,因此使用“Auto”会导致所有(或至少一些)自定义错误页面不被使用。使用“替换”也不起作用,因为响应将包含您的 http 状态代码,但其内容将为空或填充自定义错误页面。而“PassThrough”实际上会关闭 CEP,因此无法使用。

      因此,如果您想在某些情况下绕过 CEP(绕过我的意思是返回带有某些内容的状态 4xx),您将需要额外的步骤:清除错误:

      void Application_Error(object sender, EventArgs e)
      {
          var httpException = Context.Server.GetLastError() as HttpException;
          var statusCode = httpException != null ? httpException.GetHttpCode() : (int)HttpStatusCode.InternalServerError;
      
          Context.Server.ClearError();
          Context.Response.StatusCode = statusCode;
      }
      

      因此,如果您想使用 REST 响应(即 400 - 错误请求)并使用它发送一些内容,您只需在某处设置 TrySkipIisCustomErrors 并在 httpErrors 部分中将 existingResponse 设置为“自动”网络配置。现在:

      • 当没有错误(动作返回 4xx 或 5xx)并且返回了一些内容时,不使用 CEP 并将内容传递给客户端;
      • 当出现错误(抛出异常)时,错误处理程序返回的内容将被删除,因此使用 CEP。

      如果您想从您的操作返回带有空内容的状态,它将被视为空响应并显示 CEP,因此此代码还有一些改进空间。

      【讨论】:

        【解决方案7】:

        默认情况下,IIS 7 使用详细的自定义错误消息,因此我假设 Response.StatusCode 将等于 404.XX 而不仅仅是 404。

        您可以将 IIS7 配置为使用更简单的错误消息代码,或者修改您的代码来处理 IIS7 提供的更详细的错误消息。

        更多信息在这里: http://blogs.iis.net/rakkimk/archive/2008/10/03/iis7-enabling-custom-error-pages.aspx

        进一步的调查显示我的做法是错误的 - 默认情况下,详细消息不是默认设置,但如果您看到您提到的不同错误消息,它们可能已在您的盒子上打开。

        【讨论】:

        • Response.StatusCode 是一个整数,所以我看不到设置比“404”更具体的代码的方法。我已将 IIS7 配置为使用/显示自定义错误页面,如您的 URL 所示。
        • 嗯...不幸的是,我目前无法测试,因为我不在家用电脑上。如果你到那时还没有解决方案 - 我今晚会看看。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-09
        • 1970-01-01
        • 2013-06-15
        • 1970-01-01
        • 2011-02-28
        相关资源
        最近更新 更多