【问题标题】:ASP.NET MVC customError page doesn't get displayed for some of the 400 errorsASP.NET MVC customError 页面未显示某些 400 错误
【发布时间】:2015-05-06 08:26:40
【问题描述】:

我在新的 ASP.NET MVC 应用程序的自定义错误页面管理方面遇到了一个非常有趣的问题。

这个问题是这样的:
- 如果我在 URL 末尾调用带有“错误”参数的 URL(不管是哪个),例如 ..../c<,则应用程序将按照 web.config 中的说明显示正确的服务器错误页面; - 如果我将 URL 更改为更讨厌的 URL,例如 .../<c(看起来更像一个 HTML 标记,浏览器中不再显示服务器错误页面,而是得到一个普通的 YSOD像An exception occurred while processing your request. Additionally, another exception occurred while executing the custom error page for the first exception. The request has been terminated.这样的消息

根据 ELMAH,两个请求都以 400 状态码结束,消息是:
- 第一个:System.Web.HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (<). at System.Web.HttpRequest.ValidateInputIfRequiredByConfig() at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)
- 第二个:System.Web.HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (<). at System.Web.HttpRequest.ValidateInputIfRequiredByConfig() at System.Web.HttpApplication.PipelineStepManager.ValidateHelper(HttpContext context)

因此,两个错误相同,状态代码相同,但对于其中一个错误,自定义错误页面未显示。我还在调试模式下访问了 global.asax 并检查了 protected void Application_Error(object sender, EventArgs e) 中的 Server.GetLastError() 并再次发现两个错误是相同的,没有什么不同。

在 web.config 中,我的 &lt;customErrors&gt; 标签如下所示:

<customErrors mode="On" defaultRedirect="/ServerError.aspx" redirectMode="ResponseRewrite"> <error statusCode="500" redirect="/ServerError.aspx" /> <error statusCode="404" redirect="/PageNotFound.aspx" /> </customErrors>

请有人告诉我为什么这两种情况下的行为不同?

非常感谢您的宝贵时间。

【问题讨论】:

  • 您在什么平台上托管?卡西尼? IIS6? IIS7+?
  • IIS 8.5 (Windows 8.1) 和 Azure 网站。

标签: c# asp.net asp.net-mvc


【解决方案1】:

关于 IIS 7+ 中的错误处理有很多错误信息和/或过时的解决方案。主要要了解的是:-

  • .NET 4.0 对 ASP.NET 的请求验证进行了重大更改。
  • IIS 7+ 引入了一种处理自定义错误页面的新方法。

大多数人都在使用涉及所有customErrorshttpErrorsApplication_Error 处理程序的大杂烩解决方案,并且经常在httpRuntime 属性上设置requestValidationMode="2.0" 和/或完全禁用请求验证!这使得使用其他人的解决方案变得非常困难,因为所有这些都会影响行为。我快速搜索了一下,发现了几个没有接受答案的半重复项,可能是因为这个原因。

这两个错误给您带来不同行为的原因是它们发生在请求管道的不同阶段web.config 中的 customErrors 节点与您的应用程序“inside”错误交互,而请求验证发生在您的应用程序“outside”。 IIS 在到达您的应用程序代码之前拒绝危险请求,因此您的customErrors 替换不会发生。

那么我们该如何解决呢?

理想情况下,您需要一个移动部件尽可能少的解决方案。 IIS7 为我们提供了一种新方法来指定错误页面替换在 IIS 级别,而不是在应用程序级别 - httpErrors 节点。这让我们可以在一个地方捕获所有错误:-

<configuration>
  ...
  <system.webServer>
    ...
    <httpErrors errorMode="Custom" existingResponse="Replace">
      <clear />
      <error statusCode="400" responseMode="ExecuteURL" path="/ServerError.aspx"/>
      <error statusCode="403" responseMode="ExecuteURL" path="/ServerError.aspx" />
      <error statusCode="404" responseMode="ExecuteURL" path="/PageNotFound.aspx" />
      <error statusCode="500" responseMode="ExecuteURL" path="/ServerError.aspx" />
    </httpErrors>
    ...
  </system.webServer>
  ...
</configuration>

如果您关心 SEO(而且您应该关心!),您仍然必须确保您的控制器/页面设置了适当的状态代码:-

this.Response.StatusCode = 500; // etc.

您应该完全删除您的customErrors 节点。它通常用于向后兼容。您还应该确保requestValidationMode 未在httpRuntime 节点上设置

这应该可以捕获大多数错误(显然,解析 web.config 时的错误除外!)

相关:-ASP.NET MVC Custom Errors

MSDN 文档:- http://www.iis.net/configreference/system.webserver/httperrors

注意:在您的情况下,如果您想在 httpErrors 节点上设置 defaultPath,由于 ApplicationHost.config 设置,您将遇到锁冲突。你可以像我一样做,只为你关心的错误代码单独设置path,或者你可以看看解锁节点:-

我的直觉是,在 Azure 应用服务/Azure 网站等低控制环境中,麻烦大于价值。您不妨为各个状态代码设置路径。

我已经输入了full working example of using httpErrors for custom error pages up on github。你也可以see it live on azure web sites

【讨论】:

  • 到目前为止,这是我多年来看到的最详细、最完美的回应。非常感谢你!!!它工作得很好!!!
  • 我又回来了一个问题:似乎我在 web.config 中配置了一个 HttpModule (ImageProcessorModule),它拦截了我所有的调用(很正常)但是当我处理A potentially dangerous Request.RawUrl value was detected from the client,我以明文形式看到错误,并且没有显示 500 自定义错误页面;但是,如果我注释掉这个模块以不拦截请求,我会看到自定义错误页面......我错过了什么?为什么系统不显示自定义错误消息,尽管 web.config 这么说?!非常感谢!!!
  • 您最好将其作为一个单独的问题发布,并提供更多信息。我知道 httpModules 中的错误会导致自定义错误出现问题的情况,但在缩小范围之前我需要做更多工作。
  • 我会在几分钟内完成。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-05-03
  • 2012-10-08
  • 2015-04-09
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多