Scan for all actions in the site

2019-08-07 08:37发布

问题:

How do I create action links for all actions in the site?
I want to put those action links into a menu system.

I was hoping I can do something like

foreach controller in controllers {
    foreach action in controller{
        stringbuilder.writeline(
            "<li>"+actionlink(menu, action, controller)+"<li>"
        );
    }
}

回答1:

Here's my take on it:

var controllers = Assembly.GetCallingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(Controller))).ToList();
var controlList = controllers.Select(controller =>
                                     new
                                     {
                                         Actions = GetActions(controller),
                                         Name = controller.Name,
                                     }).ToList();

The method GetActions as follows:

public static List<String> GetActions(Type controller)
{
    // List of links
    var items = new List<String>();

    // Get a descriptor of this controller
    var controllerDesc = new ReflectedControllerDescriptor(controller);

    // Look at each action in the controller
    foreach (var action in controllerDesc.GetCanonicalActions())
    {
        // Get any attributes (filters) on the action
        var attributes = action.GetCustomAttributes(false);

        // Look at each attribute
        var validAction =
            attributes.All(filter => !(filter is HttpPostAttribute) && !(filter is ChildActionOnlyAttribute));

        // Add the action to the list if it's "valid"
        if (validAction)
           items.Add(action.ActionName);
    }
    return items;
}

If you need a menu system checkout the MVC Sitemap Provider, it will give you absolute control on what to render depending on the roles you've defined on your membership implementation.



回答2:

Here is approach how get all actions from controller Asp.net Mvc: List all the actions on a controller with specific attribute or Accessing the list of Controllers/Actions in an ASP.NET MVC application For achieving your goal you should find all controllers in your project with Assembly.GetExportedTypes() and filter only sub classes of ControllerBase and for each controller call new ReflectedControllerDescriptor(typeof(TController)).GetCanonicalActions() from 2nd link.