Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting All Controllers and Actions names in C#

Is it possible to list the names of all controllers and their actions programmatically?

I want to implement database driven security for each controller and action. As a developer, I know all controllers and actions and can add them to a database table, but is there any way to add them automatically?

like image 829
sagheer Avatar asked Feb 05 '14 16:02

sagheer


People also ask

How do you get the name of the current action and controller in the view?

string currentViewName = ((WebFormView)ViewContext. View). ViewPath; You can retrive both physical name of current view and action that triggered it.

Can we have same name of action method in controller?

You can have two method with the same name (and in fact it's a good practice to do that for forms). There are two requirements to have similar named methods. The methods must have different parameters. This is dictated by the programming language and is basically method overloading.

How many types of action methods are there in MVC?

Figure 2: Types of Action Result There are two methods in Action Result. One is ActionResult() and another one is ExecuteResult().

What are controllers and actions in MVC?

A controller action returns something called an action result. An action result is what a controller action returns in response to a browser request. The ASP.NET MVC framework supports several types of action results including: ViewResult - Represents HTML and markup.


3 Answers

The following will extract controllers, actions, attributes and return types:

Assembly asm = Assembly.GetAssembly(typeof(MyWebDll.MvcApplication));

var controlleractionlist = asm.GetTypes()
        .Where(type=> typeof(System.Web.Mvc.Controller).IsAssignableFrom(type))
        .SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public))
        .Where(m => !m.GetCustomAttributes(typeof( System.Runtime.CompilerServices.CompilerGeneratedAttribute), true).Any())
        .Select(x => new {Controller = x.DeclaringType.Name, Action = x.Name, ReturnType = x.ReturnType.Name, Attributes = String.Join(",", x.GetCustomAttributes().Select(a => a.GetType().Name.Replace("Attribute",""))) })
        .OrderBy(x=>x.Controller).ThenBy(x => x.Action).ToList();

If you run this code in linqpad for instance and call

controlleractionlist.Dump();

you get the following output:

enter image description here

like image 149
AVH Avatar answered Oct 15 '22 14:10

AVH


You can use reflection to find all Controllers in the current assembly, and then find their public methods that are not decorated with the NonAction attribute.

Assembly asm = Assembly.GetExecutingAssembly();

asm.GetTypes()
    .Where(type=> typeof(Controller).IsAssignableFrom(type)) //filter controllers
    .SelectMany(type => type.GetMethods())
    .Where(method => method.IsPublic && ! method.IsDefined(typeof(NonActionAttribute)));
like image 90
dcastro Avatar answered Oct 15 '22 12:10

dcastro


I was looking for a way to get Area, Controller and Action and for this I manage to change a little the methods you post here, so if anyone is looking for a way to get the AREA here is my ugly method (which I save to an xml):

 public static void GetMenuXml()
        {
       var projectName = Assembly.GetExecutingAssembly().FullName.Split(',')[0];

        Assembly asm = Assembly.GetAssembly(typeof(MvcApplication));

        var model = asm.GetTypes().
            SelectMany(t => t.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public))
            .Where(d => d.ReturnType.Name == "ActionResult").Select(n => new MyMenuModel()
            {
                Controller = n.DeclaringType?.Name.Replace("Controller", ""),
                Action = n.Name,
                ReturnType = n.ReturnType.Name,
                Attributes = string.Join(",", n.GetCustomAttributes().Select(a => a.GetType().Name.Replace("Attribute", ""))),
                Area = n.DeclaringType.Namespace.ToString().Replace(projectName + ".", "").Replace("Areas.", "").Replace(".Controllers", "").Replace("Controllers", "")
            });

        SaveData(model.ToList());
    }

Edit:

//assuming that the namespace is ProjectName.Areas.Admin.Controllers

 Area=n.DeclaringType.Namespace.Split('.').Reverse().Skip(1).First()
like image 8
Lucian Bumb Avatar answered Oct 15 '22 12:10

Lucian Bumb