2014-02-05 1 views
45

Можно ли программно отобразить имена всех контроллеров и их действия?Получение имен всех контроллеров и действий в C#

Я хочу реализовать безопасность, управляемую базой данных для каждого контроллера и действия. Как разработчик, я знаю все контроллеры и действия и могу добавить их в таблицу базы данных, но есть ли способ добавить их автоматически?

+1

Связанный: http://stackoverflow.com/questions/11300327/how-can-i-get-the-list-of-all-actions-of-mvc-controller -by-pass-controllernam – Nathan

ответ

60

Вы можете использовать отражение, чтобы найти все контроллеры в текущей сборке, а затем найти их которые не украшены атрибутом 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))); 
+0

действительно ли обязательный атрибут действия для методов действий? –

+0

@ArsenMkrt хорошая точка, я думал, что методы должны быть отмечены атрибутом «Действие». Оказывается, что все общедоступные методы - это действия, если они не украшены атрибутом «NonAction». Я обновил свой ответ. – dcastro

+0

Мы можем пойти дальше, все методы общедоступные методы с возвращаемым типом ActionResult или унаследованные от него –

1

Использование Reflection, перечислить все типы внутри сборки и фильтров классов, унаследованных от System.Web.MVC.Controller, чем список общих методов этого типов как действия

-1

Или, строгать прочь на идее @dcastro «ы и просто получить контроллеры:

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

Ниже будет распаковывать контроллеры, действия, атрибуты и типы возвращаемых значений:

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

Если вы запустите этот код в linqpad, например, и позвоните по номеру

controlleractionlist.Dump(); 

вы получите следующий результат:

enter image description here

+1

с этим ответом, я могу получить результат немедленно, в то время как принятый является трудным в использовании! – hakuna1811

+0

Что это: «MyWebDll.MvcApplication» - это класс модели? –

+0

Есть ли способ получить значение площади, если оно существует? –

1
Assembly assembly = Assembly.LoadFrom(sAssemblyFileName) 
IEnumerable<Type> 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> 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()); 
      } 
     } 
} 
6

Я искал способ получить Area, контроллер и действие, и для этого мне удалось немного изменить методы вы разместите здесь, так что если кто ищет способ получитьAREA вот мой уродливый метод (который я экономлю на 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() 
+1

Я объединил ваш код с этим расширением строки: http://stackoverflow.com/a/17253735/453142, чтобы получить область. Таким образом, вы можете получить такую ​​область: Area = n.DeclaringType.Namespace.ToString(). Substring («Areas.», «.Controllers») Вам нужно будет обновить расширение, чтобы вернуть string.empty вместо исключение и что это так. Это немного менее уродливо =) –

 Смежные вопросы

  • Нет связанных вопросов^_^