【发布时间】:2014-08-19 08:33:59
【问题描述】:
我们可能知道,例如What is the difference between customErrors and httpErrors?、CustomErrors 是在 Web 应用程序中定义错误页面的较旧方法,但这种方法存在一些问题 - 例如,如果您关心正确的 http 响应代码,因为 CustomErrors 的方法是重定向到错误页面而不是替换当前响应,通过http状态码破坏了通信的大部分语义完整性。
HttpErrors 是自 IIS 7.0 以来可用的新功能,它在服务器级别而不是应用程序级别上运行,并且更适合以有效方式处理错误响应,例如使用当前响应而不是重定向。
但是,如果在我看来,这些工件在 ASP.NET 中的基础结构现在看起来给我们带来了一些问题。
以简单配置为例
<httpErrors existingResponse="Auto" errorMode="Custom">
<remove statusCode="404"/>
<error statusCode="404" path="/Error/E404" responseMode="ExecuteURL" />
</httpErrors>
我们将 errorMode 设置为 Custom 因为我们想测试错误处理本身,我们将 existingResponse 设置为 Auto em>,会引入一个依赖于Response.TrySkipIisCustomErrors的分支:
- 正确:现有的错误响应将通过此模块未经处理,考虑到它的语义,这完全有意义。
- False:如果存在匹配规则,则现有的错误响应将被 HttpErrors 模块替换,这同样有意义。
这将理想地允许我们自己处理一些错误,例如当 ../product/id 中的产品不存在时,我们可以手动返回一个特定的 404 页面,其中包含有关缺失产品的信息,并且仍然让 HttpErrors 模块处理所有其余的内容,例如 ../products/namebutshouldbeid 或只是 ../misspelledandunmatchableurl。
但是,据我所知,这是行不通的。原因在于内部方法 System.Web.HttpResponse.ReportRuntimeError,它将在运行时错误(例如未找到控制器/操作)时调用,并且我们有一个如下所示的部分:
// always try to disable IIS custom errors when we send an error
if (_wr != null) {
_wr.TrySkipIisCustomErrors = true;
}
if (!localExecute) {
code = HttpException.GetHttpCodeForException(e);
// Don't raise event for 404. See VSWhidbey 124147.
if (code != 404) {
WebBaseEvent.RaiseRuntimeError(e, this);
}
// This cannot use the HttpContext.IsCustomErrorEnabled property, since it must call
// GetSettings() with the canThrow parameter.
customErrorsSetting = CustomErrorsSection.GetSettings(_context, canThrow);
if (customErrorsSetting != null)
useCustomErrors = customErrorsSetting.CustomErrorsEnabled(Request);
else
useCustomErrors = true;
}
在第一次调试时,我看到 useCustomErrors 设置为 false,我不明白为什么,因为我知道我有一个有效的 HttpError 配置,因为它可以工作我从控制器返回HttpNotFoundResult。
然后我意识到这不是HttpErrors,而是较旧的CustomErrors。而CustomErrors显然对HttpErrors一无所知。
“错误”
所以发生的事情是 Response.TrySkipIisCustomErrors 设置为 true 并且由于没有定义 CustomErrors,它返回详细的 404 响应。此时我们希望 HttpErrors 启动,但它不会因为 TrySkipIisCustomErrors 现在设置为 true。
我们也不能使用 CustomErrors,因为这会让我们回到令人反感的错误重定向问题。
返回HttpNotFoundResult 起作用的原因是因为它不会触发运行时错误,只返回一个 404 结果,HttpErrors 将按预期拦截,只要我们避免设置 @ 987654329@ 为真。
应该/如何处理/解决这个问题?
我在想 System.Web.HttpResponse.ReportRuntimeError 默认情况下不应该允许将 Response.TrySkipIisCustomErrors 设置为 true,因为我们有另一个依赖于此的错误处理模块。因此,此方法还需要了解任何 HttpErrors 配置,如果我们有任何 CustomErrors 配置,则避免将 TrySkipIisCustomErrors 设置为 true,或者它处理 HttpErrors 配置连同 CustomErrors 配置。
还是我错过了一些秘密魔法来解决这个问题?
【问题讨论】:
-
好吧,据我调查,您不能简单地将 CustomErrors 与 HttpErrors 结合起来并使其按预期运行。我最终得到的是完全关闭 CustomErrors,而是添加了一个 HttpModule 来检查响应的状态代码并通过直接调用我的错误控制器来替换任何错误响应。我还添加了一个标志,我们可以使用它来定义调试模式,它只会传递现有的详细错误响应,而不用我们的自定义错误替换它。
-
您是否尝试过使用“将错误发送到浏览器”和错误页面 -> 500 -> 编辑功能设置 -> “详细错误” stackoverflow.com/questions/2640526/… ?
标签: asp.net asp.net-mvc iis