简体   繁体   中英

c# How to Check if an Exception Was Already Thrown

I feel like I'm over thinking this or perhaps going the wrong way about it, but high level all I am trying to do is to catch errors that are thrown in my application, log them in the database, then redirect to a soft error page.

In my Global.asax, I have the following:

protected void Application_Error(object sender, EventArgs e)
    {
        try
        {
            ErrorLog error = new ErrorLog(Server.GetLastError().GetBaseException(), true);
            Response.Redirect("/error.aspx?id=" + error.ID);
        }
        catch(Exception err)
        {
            Response.Redirect("/error.aspx");
        }           
    }

Error log is a class I created that performs the record insertion and stuff like that.

Now the problem I am running into is that if there is something wonky with the database, like it being offline, an error in the stored procedure, etc, I get caught into an infinite loop of errors being inserted.

A solution I was trying to come up with this to resolve this behavior was to perhaps check if an error was already thrown, and if so, do not attempt to try a record insertion, but I haven't been able to find much on this.

Again, maybe I'm not going about this the correct way? Any help would be greatly appreciated. Thank you in advanced.

It is actually possible to do this, but I really don't think it's a good idea.

You can theoretically use Marshal.GetExceptionPointers() to detect it. If it returns IntPtr.Zero, it probably means that there is no exception in flight; otherwise, it probably means that there is.

I say "probably" because the MSDN documentation for Marshal.GetExceptionPointers() says under remarks:

GetExceptionPointers is exposed for compiler support of structured exception handling (SEH) only.

So that sounds like a big fat "don't use this" to me.

With that proviso, this program will actually tell you whether an exception is in flight or not, without using a try/catch to do so:

Warning: Nasty code ahead

using System;
using System.Runtime.InteropServices;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (new Test())
                {
                    // All is well.
                }

                using (new Test())
                {
                    throw new InvalidOperationException("Eeep");
                }
            }

            catch (Exception ex)
            {
                Console.WriteLine("Exception detected: " + ex.Message);
            }
        }
    }

    sealed class Test: IDisposable
    {
        public void Dispose()
        {
            Console.WriteLine(
                Marshal.GetExceptionPointers() == IntPtr.Zero
                ? "Disposing test normally."
                : "Disposing test because of an exception.");
        }
    }
}

You can make a check if you are already on that page and redirect only if you are not as:

string cTheFile = HttpContext.Current.Request.Path;

if(!cTheFile.EndsWith("error.aspx", StringComparison.InvariantCultureIgnoreCase))
    Response.Redirect("/error.aspx");

Override Exception class with ErrorLogDBInsertException and throw this one if something bad with DB stuff. Catch a specific Error

protected void Application_Error(object sender, EventArgs e)
{
    try
    {
        ErrorLog.Log();
        Response.Redirect("/error.aspx?id=" + error.ID);
    }
    catch(ErrorLogDBInsertException err)
    {

        try 
        {
            // here you can log into event log
        }
        catch {}
        Response.Redirect("/SimpleNoDBCallPage_error.aspx");

    } 
    catch(Exception err)
    {
        Response.Redirect("/PageThatCallsDB_error.aspx");
    }           
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM