将上一个错误传递给自定义错误重定向的最佳方法?

时间:2009-07-14 18:45:25

标签: asp.net caching custom-errors getlasterror

想知道您对此解决方案的看法,如果这是将错误消息传递到自定义页面的正确方法吗?

在web.config中:

    <customErrors mode="On" defaultRedirect="~/Error.aspx"></customErrors>

在Global.asax中:

<script RunAt="server">
    void Application_Error(object sender, EventArgs e)
    {
    Exception ex = Server.GetLastError();
    if (ex != null && Session != null)
    {
        ex.Data.Add("ErrorTime", DateTime.Now);
        ex.Data.Add("ErrorSession", Session.SessionID);
        HttpContext.Current.Cache["LastError"] = ex;
    }
    }

</script>

在我的Error.aspx.cs中:

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) return;

    if (HttpContext.Current.Cache["LastError"] != null)
    {
        Exception ex = (Exception)HttpContext.Current.Cache["LastError"];
        if (ex.Data["ErrorTime"] != null && ex.Data["ErrorSession"] != null)
            if ((DateTime)ex.Data["ErrorTime"] > DateTime.Now.AddSeconds(-30d) && ex.Data["ErrorSession"].ToString() == Session.SessionID)
                Label1.Text = ex.InnerException.Message;
    }
}

问题:我不想从Global.asax做一个Server.Transfer因为..我不知道。对我来说似乎很笨拙。希望能够将customErrors更改为RemoteOnly。所以必须在某个地方保存最后一个异常,但不能是Session,所以保存到Cache但是有一些额外的数据(时间和SessionID),因为Cache是​​全局的,并且希望确保不向某人显示错误的错误。


我稍微改变了我的代码。现在只是:

void Application_Error(object sender, EventArgs e)
{
    HttpContext.Current.Cache["LastError"] = Server.GetLastError().GetBaseException();
    Server.ClearError();
}

...和...

protected void Page_Load(object sender, EventArgs e)
{
    if (IsPostBack) return;

    if (HttpContext.Current.Cache["LastError"] != null)
    {
        Exception ex = (Exception)HttpContext.Current.Cache["LastError"];
        if (ex != null)
            Label1.Text = ex.Message;
    }
}

注意SessionID不存在,如果匿名用户和ex.Data.Add已经存在的密钥会导致错误让我意识到调用ClearError很重要

6 个答案:

答案 0 :(得分:7)

我认为这是一个体面的方式。这不是我的方式,但我的代码太长了,无法发布(在VB.NET中)。

我要改变的一件事是错误页面本身。而不是显示错误,请考虑将文本框添加到错误页面作为可选字段,用户可以在其中输入其电子邮件地址并单击按钮将错误报告发送给您。然后,当您收到错误报告时,您可以查看问题并回复它们。这是一种更加用户友好的方式,对于我已经完成此操作的网站来说,它的效果非常好。

除此之外,您可能还希望收集表单数据,会话数据和其他任何有价值的内容,并将其放入错误报告中。这可以使诊断问题变得更加容易。

答案 1 :(得分:1)

由于缓存是全局的,这是不可取的,因为你已经说过你可能会向某人显示错误的错误。我还应该说,出于安全原因,您不应该直接向最终用户输出错误消息。

看看这个问题:

ASP.NET custom error page server GetLastError is null

总结如下:

Server.Transfer(String.Concat("~/Error.aspx?message=", HttpUtility.UrlEncode(ex.InnerException.Message)))

而不是依靠ASP.NET使用CustomErrors部分中的设置进行重定向。

答案 2 :(得分:1)

我们做的事可能适用于您,也可能不适合您。我们在数据库中进行大量日志记录。当我们收到错误时,我们会记录它并产生错误ID。我们重定向到带有错误ID的通用页面,并在那里获取详细信息。

当然,当错误是“无法连接到数据库”但这种情况不会经常发生时,这会在它的表面上落空;)

答案 3 :(得分:1)

我必须同意n8wrl和Steve的观点,更好的方法是在数据库中记录错误,然后只向用户返回错误ID。他们实际上不需要查看技术细节,这可能会泄露敏感信息。

在我们的例子中,我们还传入用户的ID(如果可用)和发生错误的页面(当您到达全局Application_Error时,Request.URL仍然很好)。这样,我们可以更容易地追踪错误。另请注意,您不必将Global.asax与脚本标记一起使用。如果在App_Code目录中创建Global.asax.cs文件,则可以直接编写C#代码(这可能取决于项目类型)。

答案 4 :(得分:0)

Server.ClearError();

我认为在显示ErrorMessage之后,这行应放在Error.aspx.cs上。

答案 5 :(得分:0)

我负责创建自定义错误页面。一切都很简单: 在我的web.config文件中:

<customErrors mode="On">
<error statusCode="404" redirect="~/error-pages/page-not-found.aspx?error=1"
</customErrors>

并在Global.asax中的Application_Error方法中: 一些代码...

Server.Transfer("~/error-pages/error.aspx");

在自定义错误页面“error.aspx”中:Server.ClearError();

我不确切知道修改了什么,但这不再适用了。当代码到达Server.Transfer方法时,总是引发异常:执行页面的子请求时出错......

我看了一些解决方案,最后找到了这个。 我修改了我的代码,现在它似乎有效:

<customErrors mode="On" defaultRedirect="~/error-pages/error.aspx">
  <error statusCode="404" redirect="~/error-pages/page-not-found.aspx?error=1" />
</customErrors>

并在global.asax方法中:

Session["LastError"] = Server.GetLastError();

它也适用于Cache [“”]代码,但我更喜欢Session变量。

所以,谢谢你的回复。

  • 不要忘记清除自定义错误页面中的错误。这个很重要。此外,它将被指示不向用户显示所有错误。也许以某种用户友好的格式。并将所有信息提供给日志文件,或通过电子邮件或其他方式发送。

希望这很有用。