Obtendo todos os nomes de controladores e ações em c #

É possível listar os nomes de todos os controladores e suas ações programaticamente?

Eu quero implementar a segurança orientada por database para cada controlador e ação. Como desenvolvedor, conheço todos os controladores e ações e posso adicioná-los a uma tabela de database, mas existe alguma maneira de adicioná-los automaticamente?

Você pode usar a reflection para localizar todos os Controladores na assembly atual e, em seguida, encontrar seus methods públicos que não são decorados com o atributo NonAction .

 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))); 

O seguinte irá extrair controladores, ações, atributos e tipos de retorno:

 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(); 

Se você executar este código no linqpad por exemplo e chamar

 controlleractionlist.Dump(); 

você obtém a seguinte saída:

insira a descrição da imagem aqui

Eu estava procurando uma maneira de obter Area, Controller e Action e para isso eu consegui mudar um pouco os methods que você postar aqui, então se alguém está procurando uma maneira de obter o AREA aqui está meu método feio (que eu guardo para um 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()); } 

Editar:

 //assuming that the namespace is ProjectName.Areas.Admin.Controllers Area=n.DeclaringType.Namespace.Split('.').Reverse().Skip(1).First() 

Use o Reflection , enumere todos os tipos dentro da assembly e filtre as classs herdadas de System.Web.MVC.Controller , e liste os methods públicos desse tipo como ações

 Assembly assembly = Assembly.LoadFrom(sAssemblyFileName) IEnumerable types = assembly.GetTypes().Where(type => typeof(Controller).IsAssignableFrom(type)).OrderBy(x => x.Name); foreach (Type cls in types) { list.Add(cls.Name.Replace("Controller", "")); IEnumerable memberInfo = cls.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public).Where(m => !m.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), true).Any()).OrderBy(x => x.Name); foreach (MemberInfo method in memberInfo) { if (method.ReflectedType.IsPublic && !method.IsDefined(typeof(NonActionAttribute))) { list.Add("\t" + method.Name.ToString()); } } } 
 var result = Assembly.GetExecutingAssembly() .GetTypes() .Where(type => typeof(ApiController).IsAssignableFrom(type)) .SelectMany(type => type.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)) .Where(m => !m.GetCustomAttributes(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), true).Any()) .GroupBy(x => x.DeclaringType.Name) .Select(x => new { Controller = x.Key, Actions = x.Select(s => s.Name).ToList() }) .ToList(); 

resposta @decastro é bom. Eu adiciono este filtro para retornar somente ações públicas que foram declaradas pelo desenvolvedor.

  var asm = Assembly.GetExecutingAssembly(); var methods = asm.GetTypes() .Where(type => typeof(Controller) .IsAssignableFrom(type)) .SelectMany(type => type.GetMethods()) .Where(method => method.IsPublic && !method.IsDefined(typeof(NonActionAttribute)) && ( method.ReturnType==typeof(ActionResult) || method.ReturnType == typeof(Task) || method.ReturnType == typeof(String) || //method.ReturnType == typeof(IHttpResult) || ) ) .Select(m=>m.Name); 

Ou, para reduzir a ideia do @dcastro e obter os controladores:

 Assembly.GetExecutingAssembly() .GetTypes() .Where(type => typeof(Controller).IsAssignableFrom(type))