微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

asp.net – CustomErrors vs HttpErrors – 一个重大的设计缺陷?

我们可能知道,例如,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,这将引入依赖于Response.TrySkipIisCustomErrors的分支:

> True:现有的错误响应将通过此模块未经处理,考虑到它的语义含义,这是完全合理的.
> False:如果HttpErrors模块具有匹配规则,则现有的错误响应将被替换为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的原因是因为它不会触发运行时错误,只返回HttpErrors将按预期拦截的404结果,只要我们避免将Response.TrySkipIisCustomErrors设置为true即可.

应该如何处理/解决这个问题?

我认为认情况下不允许System.Web.HttpResponse.ReportRuntimeError将Response.TrySkipIisCustomErrors设置为true,因为我们有另一个依赖于此的错误处理模块.因此,此方法也需要了解任何HttpErrors配置,或者通过避免将TrySkipIisCustomErrors设置为true(如果我们有任何CustomErrors配置),或者它与CustomErrors配置一起处理HttpErrors配置.

或者我错过了一些秘密魔法来解决这个问题?

解决方法

就像你一样,我认为ASP.NET不应该设置TrySkipIisCustomErrors或者可以添加一个选项,以便我们可以避免它.

作为一种解决方法,我构建了一个能够将查询传输到ASP.NET MVC控制器的ASPX页面.

ErrorHandler.aspx.cs

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ErrorHandler.aspx.cs" Inherits="Guillaume.ErrorHandler" %>

代码背后

protected void Page_Load(object sender,EventArgs e)
{
  //Get status code
  var queryStatusCode = Request.QueryString.Get("code");
  int statusCode;
  if (!int.TryParse(queryStatusCode,out statusCode))
  {
    var lastError = Server.GetLastError();
    HttpException ex = lastError as HttpException;
    statusCode = ex == null ? 500 : ex.GetHttpCode();
  }
  Response.StatusCode = statusCode;

  // Execute a route
  RouteData routeData = new RouteData();
  string controllerName = Request.QueryString.Get("controller") ?? "Errors";
  routeData.Values.Add("controller",controllerName);
  routeData.Values.Add("action",Request.QueryString.Get("action") ?? "Index");

  var requestContext = new RequestContext(new HttpContextwrapper(Context),routeData);
  IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext,controllerName);
  controller.Execute(requestContext);
}

在web.config中的用法

<configuration>
    <system.web>
        <customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="/Content/ErrorHandler.aspx">
            <error statusCode="404" redirect="/Content/ErrorHandler.aspx?code=404&amp;controller=Errors&amp;action=NotFound" />
        </customErrors>
    </system.web>
</configuration>

常规浏览器请求的行为是正确的:当出现错误并返回错误代码时,将显示错误页面.
它在AJAX / Web API请求上也是正确的:不返回错误页面.我们在JSON或XML中得到可解析的错误.

如果要将非ASP.NET错误重定向自定义错误,可以添加httpErrors部分.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WPF...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这...
Some samples are below for ASP.Net web form controls:(from http://www.visualize.uk.com/resources/asp
问题描述: 对于未定义为 System.String 的列,唯一有效的值是(引发异常)。 For columns not defined as System.String, the only vali
最近用到了CalendarExtender,结果不知道为什么发生了错位,如图在Google和百度上找了很久,中文的文章里面似乎只提到了如何本地化(就是显示中文的月份)以及怎么解决被下拉框挡住的问题,谈
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence changed a lot since 1.1. Here is the order: App
静态声明: &#39; Style=&quot;position: relative&quot; AppendDataBoundItems=&quot;True&quot;&gt; (无 或 空 或
以下内容是从网络上搜集资料,然后整理而来的。不当之处,请不吝指教。(The following were from network, and edited by myself. Thanks in a
Imports System Imports System.Reflection Namespace DotNetNuke &#39;*********************************
Ok so you have all seen them: “8 million tools for web development”, “5 gagillion tools that if you