2

From a custom HtmlHelper extension, I would like to get the MethodInfo for the action.

I know I can get the Type of the controller, and the string name of the action from:

public static void MyHelper(this HtmlHelper helper)
{
  var controller = helper.ViewContext.Controller;
  var actionName = ViewContext.Controller.ValueProvider.GetValue("action").RawValue;
}

But I really want the MethodInfo because I want to pull a custom Attribute off the action method. I can't just call reflection .GetMethod(actionName); because there is usually more than 1 with the same name (two actions with the same name, one for the http GET and one for the POST).

At this point I am thinking I might have to manually get all methods with the action name, and run through all the info in ViewContext.Controller.ValueProvider to see what method has parameters that match the values in the provider, but I am hoping the MethodInfo is already available somewhere...

CodingWithSpike
  • 42,906
  • 18
  • 101
  • 138

3 Answers3

2

There's really no easy way to achieve that. Normally you decorate controller actions with custom action filters (not just any type of attributes). So you could have this custom action filter inject some information in the current HttpContext so that the HTML helper would know that the view was served from a controller action decorated with this custom action filter.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
0

One way to get the MethodInfo of the current Action is to use a combination of the StackTrace and the RouteData.

You need to filter out all the unwanted StackTrace Frames.

The code will work from nested Controller class where you put your common helpers, or you can place in parent Controller

public FooController : BaseController
{
    [YourCustomAttribute]
    public ActionResult Edit(int id)
    {

       MethodInfo action = CurrentExecutingAction();

       // your code here, now you can get YourCustomAttribute Attribute for the Action

    }
}

public abstract class BaseController : Controller
{

    protected MethodInfo CurrentExecutingAction(Type type = null)
    {
        type = type ?? GetType();
        var rd = ControllerContext.RouteData;
        var currentAction = rd.GetRequiredString("action");

        StackTrace s = new StackTrace();
        return s.GetFrames()
            .Select(x => x.GetMethod())
            .Where(x => x is MethodInfo && x.Name == currentAction && x.DeclaringType.IsAssignableFrom(type))
            .Select(x => (MethodInfo) x)
            .LastOrDefault();
    }
}
Adam
  • 2,082
  • 2
  • 19
  • 17
0

I have answered my own question, that is very similar to this.

Given a live controller, and the name of another controller and action, and also the http method (GET, POST), I have developed a method that can get the attributes.

Something like this:

public static Attribute[] GetAttributes(
    this Controller @this,
    string action = null,
    string controller = null,
    string method = "GET")

You call it like this:

var attrs = liveController
    .GetAttributes("anotherAction", "anotherController", "POST");
Community
  • 1
  • 1
Miguel Angelo
  • 23,796
  • 16
  • 59
  • 82