すべてのコントローラーの名前とそのアクションをプログラムでリストすることは可能ですか?
各コントローラーとアクションにデータベース駆動型のセキュリティを実装したい。開発者として、私はすべてのコントローラーとアクションを知っており、それらをデータベース表に追加できますが、それらを自動的に追加する方法はありますか?
リフレクションを使用して、現在のアセンブリ内のすべてのコントローラーを検索し、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)));
以下は、コントローラー、アクション、属性、および戻り値の型を抽出します。
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();
次の出力が得られます。
エリア、コントローラー、アクションを取得する方法を探していたので、ここで投稿するメソッドを少し変更することができました。だから誰かがget the[〜#〜] 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()
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());
}
}
}
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();
Reflection を使用して、アセンブリ内のすべての型を列挙し、System.Web.MVC.Controller
、このタイプのパブリックメソッドをアクションとしてリストする
@decastroの回答は良いです。このフィルターを追加して、開発者によって宣言されたパブリックアクションのみを返します。
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<ActionResult>) ||
method.ReturnType == typeof(String) ||
//method.ReturnType == typeof(IHttpResult) ||
)
)
.Select(m=>m.Name);
または、@ dcastroのアイデアに手を出し、コントローラーを入手するだけです。
Assembly.GetExecutingAssembly()
.GetTypes()
.Where(type => typeof(Controller).IsAssignableFrom(type))