asp.net-mvcstack-traceonactionexecuting

Alternative to StackTrace.GetFrame... to finding the action on a controller that called a method


Setup:

I have written an ASP.NET MVC wizard, based originally on Steve Sanderson's wizard (Pro ASP.NET MVC 2 Framework). My wizard is generic and is a dream.

Each Wizard step is an action.

However, I have now released an app that uses the wizard extensively. Obviously, the app is in release mode.

The WizardController<> class is the base class to all my wizards. It has an OnActionExecuting method that I suspect can provide the solution to my problem. The question is how, or rather, to traverse the stack in the right order, what the problem is...

The Problem:

The code, deep in the WizardController, uses:

var stackTrace = new StackTrace();
string actionName = stackTrace.GetFrame(n).GetMethod().Name

to get the name of the action that has called this code (where n is the frame I know is the calling action... in debug mode that is). This allows me to establish which wizard step / action I am on.

This works fine in debug mode, but in release mode, the compiler optimises my code. So n may, or may not, represent the correct frame in my stack.

The reality is that, in release mode, sometimes n does not represent the correct frame. And sometimes is not good enough. Sometimes is my problem. I want a bullet proof solution.

Question:

So what alternative to using stacktrace?? I suspect I can use my OnActionExecuting method to grab the name of the action, which is what I need, as this name is what identifies the step in my wizard.

But how?

Forget to be or not to be. How? That is the question.


Solution

  • OK, writing the post made me realise that the answer was staring at me blue in the face.

    The ActionExecutingContext parameter of the OnActionExecuting method gives me the handle I need on the Action name, as follows:

    In my WizardController class I add the following:

    private string ActionName { get; set; } 
    protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
        ActionName = filterContext.ActionDescriptor.ActionName; 
        // All the other stuff...
    }
    

    I can now use the ActionName property instead of:

    stackTrace.GetFrame(n).GetMethod().Name
    

    where n might be known in debug mode, but is very definitely not known for sure in release mode.

    Phew!

    Hope this helps someone else who, like Narcissus, has fallen into the reflection trap.