Pouria Montakhabi
Pouria Montakhabi

Reputation: 255

How to get all action , controller and area names while running asp core 3.1

i have an asp.net core 3.1 application and i want to get all controller , action and area names when my application is running like get action names with reflection in mvc. Is there any way ?

Upvotes: 1

Views: 4107

Answers (4)

MoHaMMaD
MoHaMMaD

Reputation: 19

I wrote new code with a Controller and Action DisplayNames.

Assembly assembly = Assembly.GetExecutingAssembly();

        var controllersList = assembly.GetTypes().Where(ctype => typeof(Controller).IsAssignableFrom(ctype)).Select(type => new { ty = type, methods = type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).Where(y => Attribute.IsDefined(y, typeof(LogRequestAttribute))) }).Where(type => type.methods.Any(x => Attribute.IsDefined(x, typeof(LogRequestAttribute)))).Select(controller => new
        {
            AreaName = (controller.ty.GetCustomAttribute(typeof(AreaAttribute)) as AreaAttribute)?.RouteValue,
            ControllerTitle = (controller.ty.GetCustomAttribute(typeof(DisplayNameAttribute)) as DisplayNameAttribute)?.DisplayName,
            ControllerName = controller.ty.Name,
            Actions = controller.methods.Select(action => new
            {
                ActionTitle = (action.GetCustomAttribute(typeof(DisplayNameAttribute)) as DisplayNameAttribute)?.DisplayName,
                ActionName = action.Name,
            }).ToList(),
        }).ToList();

        // group by on area
        var areaList = controllersList.GroupBy(group => group.AreaName).Select(ar => new
        {
            AreaName = ar.Key,
            Controllers = ar.Select(co => new
            {
                ControllerTitle = co.ControllerTitle,
                ControllerName = co.ControllerName,
                Actions = co.Actions,
            }).ToList(),
        }).ToList();

Upvotes: 0

BCA
BCA

Reputation: 8526

In my application I didn't require finding areas, so I ended up creating a simplified version based on the accepted answer. If it's useful to anyone else, here it is:

public static class ControllerActionEnumerator
{
    public static List<ControllerAndItsActions> GetAllControllersAndTheirActions()
    {
        Assembly asm = Assembly.GetExecutingAssembly();
        IEnumerable<Type> controllers = asm.GetTypes().Where(type => type.Name.EndsWith("Controller"));
        var theList = new List<ControllerAndItsActions>();
        
        foreach (Type curController in controllers)
        {
            List<string> actions = curController.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
                .Where(m => m.CustomAttributes.Any(a => typeof(HttpMethodAttribute).IsAssignableFrom(a.AttributeType)))
                .Select(x => x.Name)
                .ToList();
            
            theList.Add(new ControllerAndItsActions(curController.Name, actions));
        }

        return theList;
    }
}

public class ControllerAndItsActions
{
    public string Controller { get; }
    public List<string> Actions { get; }

    public ControllerAndItsActions(string controller, List<string> actions) => (Controller, Actions) = (controller, actions);
}

Upvotes: 1

Rena
Rena

Reputation: 36765

Try this:

1.Model:

public class ControllerActions
{
    public string Controller { get; set; }
    public string Action { get; set; }
    public string Area { get; set; }
}

2.Display the Controller,Action and Area Name:

[HttpGet]
public List<ControllerActions> Index()
{
    Assembly asm = Assembly.GetExecutingAssembly();
    var controlleractionlist = asm.GetTypes()
            .Where(type => typeof(Controller).IsAssignableFrom(type))
            .SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public))
            .Select(x => new
            {
                Controller = x.DeclaringType.Name,
                Action = x.Name,
                Area = x.DeclaringType.CustomAttributes.Where(c => c.AttributeType == typeof(AreaAttribute))

            }).ToList();
    var list = new List<ControllerActions>();
    foreach (var item in controlleractionlist)
    {
        if (item.Area.Count() != 0)
        {
            list.Add(new ControllerActions()
            {
                Controller = item.Controller,
                Action = item.Action,
                Area = item.Area.Select(v => v.ConstructorArguments[0].Value.ToString()).FirstOrDefault()
            });
        }
        else
        {
            list.Add(new ControllerActions()
            {
                Controller = item.Controller,
                Action = item.Action,
                Area = null,
            });
        }
    }
    return list;
}

Upvotes: 4

Likol Lee
Likol Lee

Reputation: 259

Try this:

ControllerFeature controllerFeature = new ControllerFeature();
this.ApplicationPartManager.PopulateFeature(controllerFeature);
IEnumerable<TypeInfo> typeInfos = controllerFeature.Controllers;

ApplicationPartManager must use DI to your class.

Upvotes: 2

Related Questions