5

Is there a way to get a list of all Actions Methods of my MVC 3 project?

iCollect.it Ltd
  • 92,391
  • 25
  • 181
  • 202
Mats Hofman
  • 7,060
  • 6
  • 33
  • 48
  • Do you mean Actions or Views? If you mean Views do you include Partial views? Also which viewengine? If you're using the default then you could use reflection to get a list of every class in your assembly/namespace that inherits from System.Web.Mvc.ViewPage or ViewPage. Actions you can do the same kind of thing - use reflection to identify all the classes inheriting from Controller and all their public methods that return an ActionResult derivative. – RichardW1001 Apr 27 '11 at 09:20
  • I want the Actions in VS – Mats Hofman Apr 27 '11 at 09:44
  • 1
    Please update the question with that additional information. – Richard Apr 27 '11 at 10:41

2 Answers2

10

This will give you a dictionary with the controller type as key and an IEnumerable of its MethodInfos as value.

        var assemblies = AppDomain.CurrentDomain.GetAssemblies(); // currently loaded assemblies
        var controllerTypes = assemblies
            .SelectMany(a => a.GetTypes())
            .Where(t => t != null
                && t.IsPublic // public controllers only
                && t.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) // enfore naming convention
                && !t.IsAbstract // no abstract controllers
                && typeof(IController).IsAssignableFrom(t)); // should implement IController (happens automatically when you extend Controller)
        var controllerMethods = controllerTypes.ToDictionary(
            controllerType => controllerType,
            controllerType => controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => typeof(ActionResult).IsAssignableFrom(m.ReturnType)));

It looks in more than just the current assembly and it will also return methods that, for example, return JsonResult instead of ActionResult. (JsonResult actually inherits from ActionResult)

Edit: For Web API support

Change

&& typeof(IController).IsAssignableFrom(t)); // should implement IController (happens automatically when you extend Controller)

to

&& typeof(IHttpController).IsAssignableFrom(t)); // should implement IHttpController (happens automatically when you extend ApiController)

and remove this:

.Where(m => typeof(ActionResult).IsAssignableFrom(m.ReturnType))

Because Web API methods can return just about anything. (POCO's, HttpResponseMessage, ...)

Moeri
  • 9,104
  • 5
  • 43
  • 56
  • +1 for a method that returns more details (I like how it groups the 'Actions' with their respective 'Controllers') – JakeJ Oct 07 '13 at 22:42
  • In case of webapi this code get many redundant methods - constructors, all public properties (inherited from ApiController), etc. More precise method described here: http://stackoverflow.com/questions/28069206/how-can-i-get-the-list-of-all-actions-of-apicontroller – LbISS Dec 28 '15 at 19:16
7

You can use this to reflect over the assemblies at runtime to produce a list of methods in Controllers that return ActionResult:

    public IEnumerable<MethodInfo> GetMvcActionMethods()
    {
        return
            Directory.GetFiles(Assembly.GetExecutingAssembly().Location)
                .Select(Assembly.LoadFile)
                .SelectMany(
                    assembly =>
                    assembly.GetTypes()
                            .Where(t => typeof (Controller).IsAssignableFrom(t))
                            .SelectMany(type => (from action in type.GetMethods(BindingFlags.Public | BindingFlags.Instance) 
                                                 where action.ReturnType == typeof(ActionResult) 
                                                 select action)
                                        )
                    );
    }

This will give you the actions, but not the list of Views (i.e. it won't work if you can use different views in each action)

Mark Keats
  • 1,390
  • 8
  • 15
  • 1
    This method will not include action methods that return "FileContentResult", "JsonResult", ... See my response below – Moeri Jun 11 '13 at 13:04