对于400个错误中的某些错误,不会显示ASP.NET MVC customError页面

Edi*_*Edi 9 c# asp.net asp.net-mvc

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

这个问题是这样的:
- 如果我在URL的末尾用一个"坏"参数调用一个URL(无关紧要)..../c<,那么应用程序就会按照Web中的说明显示正确的服务器错误页面.配置;
- 如果我将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并检查了Server.GetLastError()in protected void Application_Error(object sender, EventArgs e)和again,两个错误都是一样的,没有什么不同.

在web.config中,这是我的<customErrors>标记的样子:

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

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

非常感谢您的宝贵时间.

Iai*_*way 14

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

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

大多数人都使用涉及到所有的大杂烩解决方案customErrors,httpErrorsApplication_Error处理程序,并经常设置requestValidationMode="2.0"httpRuntime和财产/或完全禁用请求验证!这使得使用其他人的解决方案变得非常困难,因为任何和所有这些都会影响行为.我快速搜索了一下,我找到了几个没有接受答案的半复制品,可能是因为这个原因.

这两个错误给您带来不同行为的原因是它们发生在请求管道的不同阶段.您的应用中的customErrors节点web.config与应用程序内部的错误进行交互,而请求验证则在应用程序" 外部 "进行.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>
Run Code Online (Sandbox Code Playgroud)

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

this.Response.StatusCode = 500; // etc.
Run Code Online (Sandbox Code Playgroud)

您应该customErrors完全删除您的节点.它通常用于向后兼容.你也应该确保requestValidationMode设置上的httpRuntime节点.

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

相关: - ASP.NET MVC自定义错误

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

注意:在您的情况下,如果要defaultPathhttpErrors节点上进行设置,则会因ApplicationHost.config设置而导致锁定违规.你可以像我一样做,只path为你关心的错误代码单独设置,或者你可以看看解锁节点: -

我的直觉是,在Azure App Service/Azure Web Sites等低控制环境中,它比它的价值更大.您也可以设置各个状态代码的路径.

在github上提供了一个完整的工作示例,使用httpErrors来自定义错误页面.您也可以在天蓝色的网站上看到它.