19

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?

leppie
  • 115,091
  • 17
  • 196
  • 297
SKumar
  • 1,227
  • 6
  • 18
  • 29
  • 1
    The simple answer? It's the method at the top of the call stack. This is the method that was called most recently before the exception occurred. :) – Chiramisu Mar 31 '13 at 07:05
  • I resolved by checking this answer http://stackoverflow.com/questions/27997276/get-method-name-that-threw-exception – Sarath Subramanian Feb 15 '16 at 07:46

3 Answers3

24

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.

Ani
  • 111,048
  • 26
  • 262
  • 307
4

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.

Chris Gessler
  • 22,727
  • 7
  • 57
  • 83
  • What is GetType in reference to? Is this another method you created? The built in GetType needs an object to reference. – KingOfHypocrites Jun 03 '14 at 18:53
  • @KingOfHypocrites - GetType() is being called from the current class. – Chris Gessler Jun 05 '14 at 12:33
  • 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`](http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod(v=vs.110).aspx) – Peter Duniho Jan 17 '15 at 08:26
  • @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. – Chris Gessler Jan 17 '15 at 14:57
  • 1
    @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. – Bjorn May 27 '20 at 12:30
1

Look at the stacktrace.

It's a property on the exception.

leppie
  • 115,091
  • 17
  • 196
  • 297