How to get the name of the method that caused the exception

35,393

Solution 1

There's a TargetSite property on System.Exception that should come in handy.

Gets the method that throws the current exception.

In your case, you probably want something like:

catch (Exception ex)
{
   MethodBase site = ex.TargetSite;
   string methodName = site == null ? null : site.Name;
   ...           
}

It's worth pointing out some of the issues listed:

If the method that throws this exception is not available and the stack trace is not a null reference (Nothing in Visual Basic), TargetSite obtains the method from the stack trace. If the stack trace is a null reference, TargetSite also returns a null reference.

Note: The TargetSite property may not accurately report the name of the method in which an exception was thrown if the exception handler handles an exception across application domain boundaries.

You could use the StackTrace property as @leppie suggests too, but do note that this is a string representation of the frames on the stack; so you'll have to manipulate if you only want the name of the method that threw the execption.

Solution 2

It's in the StackFrame...

private string GetExecutingMethodName()
{
    string result = "Unknown";
    StackTrace trace = new StackTrace(false);
    Type type = this.GetType();

    for (int index = 0; index < trace.FrameCount; ++index)
    {
        StackFrame frame = trace.GetFrame(index);
        MethodBase method = frame.GetMethod();

        if (method.DeclaringType != type && !type.IsAssignableFrom(method.DeclaringType))
        {
            result = string.Concat(method.DeclaringType.FullName, ".", method.Name);
            break;
        }
    }

    return result;
}

This method was written for an Logging handler class and the use of GetType() simply eliminates the methods within the Logging handler class from being returned as the last executing method. Since the Logging handler class was written for more than just logging exceptions, a new StackTrace object was required. Obviously, for finding "the method that threw the exception" GetType() might not be necessary.

If you just want the top of the stack, take the first frame, call GetMethod() and return that, or simply use TargetSite. GetType() could then be removed. Also note, that the Exception would need to be passed in to create the StackTrace object. For example:

class Program
{
    static void Main(string[] args)
    {
        try
        {
            Test();
        }
        catch (Exception ex)
        {

            // does not work properly - writes "Main"
            Console.WriteLine(MethodBase.GetCurrentMethod());

            // properly writes "TestConsole.Program.Test"
            Console.WriteLine(GetExecutingMethodName(ex));

            // properly writes "Test"
            Console.WriteLine(ex.TargetSite.Name);
        }

        Console.ReadKey();
    }


    static void Test()
    {
        throw new Exception("test");
    }

    private static string GetExecutingMethodName(Exception exception)
    {
        var trace = new StackTrace(exception);
        var frame = trace.GetFrame(0);
        var method = frame.GetMethod();

        return string.Concat(method.DeclaringType.FullName, ".", method.Name);
    }
}

Basically, if TargetSite() does what you want, then go no further. But, often times in Logging handlers, an exception object is not available (i.e. tracing and auditing) so a new StackTrace() object is necessary for retrieving the last executed method, the one BEFORE the Logging method.

Solution 3

Look at the stacktrace.

It's a property on the exception.

Share:
35,393
SKumar
Author by

SKumar

Updated on July 09, 2022

Comments

  • SKumar
    SKumar almost 2 years

    My code looks as below.

    try
    {
        _productRepo.GetAllProductCategories();
    }
    catch (Exception ex)
    {
        //Do Something
    }
    

    I need a way to show the method name, suppose in the above case if any exception is thrown in the GetAllProductCategories() method, I need to get this method name i.e. "GetAllProductCategories()" as my result. Can any one suggest me how to do this?

  • KingOfHypocrites
    KingOfHypocrites almost 10 years
    What is GetType in reference to? Is this another method you created? The built in GetType needs an object to reference.
  • Chris Gessler
    Chris Gessler almost 10 years
    @KingOfHypocrites - GetType() is being called from the current class.
  • Peter Duniho
    Peter Duniho over 9 years
    I don't see how this applies to the question asked. This code generates a whole new StackTrace object, unrelated to the exception's stack trace. Also, .NET already has a perfectly good (and more reliable) way to obtain the MethodInfo object for the currently executing method: MethodBase.GetCurrentMethod
  • Chris Gessler
    Chris Gessler over 9 years
    @PeterDuniho - It demonstrates that the current executing method name is available from the StackFrame. So in an error condition, the Exception object can be used to create a StackTrace object which can be used to get the StackFrames. The method could be easily modified to accept an Exception object, but the code is more of a demonstration of how to use StackFrame. Also note that MethodBase.GetCurrentMethod() will only provide the name of the current method being executed, not the method that threw the exception.
  • Bjorn
    Bjorn almost 4 years
    @ChrisGessler How can I get the mathod in an async method? The stacktrace is more complex and I dont see the "real" method name here.