2014-02-05 113 views
45

是否可以通过编程方式列出所有控制器的名称及其操作?获取C#中的所有控制器和操作名称

我想为每个控制器和操作实现数据库驱动的安全性。作为一名开发人员,我知道所有的控制器和操作,并且可以将它们添加到数据库表中,但有什么方法可以自动添加它们吗?

+1

相关:http://stackoverflow.com/questions/11300327/how-can-i-get-the-list-of-all-actions-of-mvc-controller-by-传递 - 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好点,我认为方法必须标记为'Action'属性。事实证明,除非使用'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这里是我的丑方法(我保存到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()); 
    } 

编辑:

//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而不是例外,它是。这是一个不太丑陋的=) –

相关问题