Search code examples
asp.netcachingcustom-errorsgetlasterror

Best way to pass last error to custom error redirect?


Was wondering what you thought of this solution, if this is right way to pass an error message to a custom page?

In web.config:

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

In 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>

In my 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;
    }
}

Of issue: I don't want to do a Server.Transfer from Global.asax because.. I don't know. Seemed clumsy to me. Want to be able to change customErrors to RemoteOnly. So have to save last exception somewhere, but can't be Session, so save to Cache but with some extra data (time and SessionID) since Cache is global and want to make sure not showing wrong error to someone.


I changed my code somewhat. Now it's just:

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

...and...

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;
    }
}

Note SessionID not there if anonymous user, and ex.Data.Add a key that's already there will cause error making me realize it's important to call ClearError


Solution

  • I think that's a decent way to do it. It's not the way I do it, but my code is too lengthy to post (and in VB.NET).

    One thing I would change is the error page itself. Instead of displaying the error, consider adding a textbox to the error page as an optional field where the user can enter their email address and click a button to send the error report to you. Then when you receive the error report you can look at the problem and reply to them. It's a much more user friendly way to do it and it's worked out quite well for the sites I've done this on.

    Along those lines, you might also want to gather form data, session data, and anything else of value and put that into the error report as well. This can make diagnosing problems much easier.