Asp.net 为什么我在做服务器时看到2个错误页面。从应用程序传输错误和错误模式=";海关;?

Asp.net 为什么我在做服务器时看到2个错误页面。从应用程序传输错误和错误模式=";海关;?,asp.net,iis-7,error-handling,Asp.net,Iis 7,Error Handling,我的问题与此密切相关 下面是一个简短的概要:我的应用程序正在经典模式下运行。 我在Global.asax中有以下代码 protected void Application_Error(Object sender, EventArgs e) { // ... boring stuff... HttpContext.Current.Server.Transfer("~/MyErrorPage.aspx", true); } 当出现错误时,如果

我的问题与此密切相关

下面是一个简短的概要:我的应用程序正在经典模式下运行。 我在Global.asax中有以下代码

    protected void Application_Error(Object sender, EventArgs e)
    {
        // ... boring stuff...
        HttpContext.Current.Server.Transfer("~/MyErrorPage.aspx", true);
    }
当出现错误时,如果

<httpErrors errorMode="Detailed" />
如果我从IIS错误页面部分删除默认的500错误页面,那么我会得到以下输出(注意,我得到的是“页面无法显示…”,而不是自定义的500页面)

由于发生内部服务器错误,无法显示页面。
如果我使用调试器单步执行代码,那么当我跨过
Server.Transfer
语句时,我会看到IIS 500页面被刷新到客户端。
然后,在MyErrorPage.aspx的正常页面生命周期之后,我的错误页面会被发送到浏览器(正如您所期望的那样)。 我已尝试(绝望地)在Server.Transfer之前清除响应的内容(
HttpContext.Current.response.Clear()
),但没有效果。 在传输之前,我还尝试调用了
Server.ClearError()
,但也没有效果

现在根据链接的问题,“修复”是设置
errormode=“Detailed”
,但我不想看到ASP.Net中未处理的错误的详细错误页面-例如,如果我输入url
myApp/DoesNotExist.html
,我宁愿看到IIS自定义404页面而不是详细页面。[我们的一些客户绝对坚持用户永远不会看到详细的错误页面,因为这被认为是一个潜在的安全弱点。]

另一个“修复”是重定向,而不是执行服务器传输,但如果可能,我更愿意执行传输:执行传输意味着浏览器的URL保持不变,这意味着,例如,如果由于应用程序刚刚启动而发生错误,他们可以按F5重试请求。重定向显然会将浏览器地址更改为错误页面

有人能解释我为什么会看到这种行为吗?有人有解决办法吗

提前谢谢

编辑

我设计了一个小应用程序来演示这种行为:

[确保应用程序以经典模式运行。]

如果单击同时设置了transfer和setstatus参数的链接,则会看到问题。

将以下属性添加到您的
标记中:

existingResponse="PassThrough"
这应该可以解决问题<当
errorMode=“Detailed”
时,code>PassThrough是默认值


更多信息请访问

Response Response.TrySkipIisCustomErrors上有一个属性,它显然是为了防止IIS注入自己的错误页面代码。假设您能够在错误以某种方式发生时将其设置为true,这样您就不会获得针对实际错误的自定义错误页,但404仍保留在IIS中。

如果自定义错误页逻辑仅基于错误号,那么您应该在web.config中定义自定义错误页。并根据Server.GetLastError()中的状态代码在常规错误页中设置状态代码。 如果指定defaultResponseMode=“ExecuteURL”,则客户端浏览器中将具有所需页面的URL

<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/CustomErrorPage.aspx" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/ErrorPages/404.aspx"/>
      <error statusCode="500" redirect ="~/ErrorPages/500.aspx"/>
</customErrors>
</system.web>

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace" defaultPath="~/ErrorPages/CustomErrorPage.aspx" defaultResponseMode="ExecuteURL">
      <error statusCode="404" path="~/ErrorPages/404.aspx"/>
      <error statusCode="500" path ="~/ErrorPages/500.aspx"/>
    </httpErrors>
</system.webServer>

通过这种方式,您省去了对Server.Transfer的需要(这是由enviromnet隐式完成的),并且您有一个用于未明确处理的错误的通用页面。

我尝试了此设置,它确实避免了看到2个错误页面的问题,但在要(以及其他我希望由IIS处理的此类错误)我什么也没有得到,浏览器出现了“oops Things is Breaked”错误。为此,我认为您还需要设置defaultPath=“~/MyErrorPage.aspx”在httpErrors标记中。啊-我会尝试一下。但是,即使这意味着我得到了一些错误页面而不是空白页面,我也将不得不在同一页面上处理404401500个错误(好的,这些错误至少不是从我的代码中产生的)。您可以使用Server.Transfer()根据状态代码或检查上下文,也可以从错误页面中选择。错误或…TrySkipIisCustomErrors在默认情况下已为true(因为我的应用程序以经典模式运行)。我已尝试了设置,但对行为没有影响。:(感谢您的响应。不幸的是,出现了多个不同的错误。)(每个都需要自己的错误页面)可以生成500个错误。在这种情况下,您可以尝试使用服务器。从您的500.aspx传输(将逻辑从global.asax移动到500.aspx)看看是否有效?(我无法运行附加的示例,因为无论我尝试加载哪个页面,我都会不断得到500个错误。)
existingResponse="PassThrough"
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/CustomErrorPage.aspx" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/ErrorPages/404.aspx"/>
      <error statusCode="500" redirect ="~/ErrorPages/500.aspx"/>
</customErrors>
</system.web>

<system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace" defaultPath="~/ErrorPages/CustomErrorPage.aspx" defaultResponseMode="ExecuteURL">
      <error statusCode="404" path="~/ErrorPages/404.aspx"/>
      <error statusCode="500" path ="~/ErrorPages/500.aspx"/>
    </httpErrors>
</system.webServer>
    Exception ex = Server.GetLastError();
    if (ex is HttpException){
        Response.StatusCode = ((HttpException)ex).GetHttpCode();
    }