Use Reflection, enumerate all types inside the assembly and filter classes inherited from System.Web.MVC.Controller, than list public methods of this types as actions
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.
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 theAREA here is my ugly method (which I save to an xml):
(Just change the last ForEach() clause as my model was encapsulated inside another model).
The corresponding ApiHelpViewModel is :
public class ApiHelpEndpointViewModel
{
public string Endpoint { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public string DisplayableName { get; set; }
public string Description { get; set; }
public string EndpointRoute => $"/api/{Endpoint}";
public PropertyInfo[] Properties { get; set; }
public List<IList<CustomAttributeTypedArgument>> PropertyDescription { get; set; }
}
As my endpoints return IQueryable<CustomType>, the last property (PropertyDescription) contains a lot of metadatas related to CustomType's properties. So you can get the name, type, description (added with a [Description] annotation) etc... of every CustomType's properties.
It goes further that the original question, but if it can help someone...
UPDATE
To go even further, if you want to add some [DataAnnotation] on fields you can't modify (because they've been generated by a Template for example), you can create a MetadataAttributes class :
[MetadataType(typeof(MetadataAttributesMyClass))]
public partial class MyClass
{
}
public class MetadataAttributesMyClass
{
[Description("My custom description")]
public int Id {get; set;}
//all your generated fields with [Description] or other data annotation
}
BE CAREFUL : MyClassMUST be :
A partial class,
In the same namespace as the generated MyClass
Then, update the code which retrieves the metadatas :
All these answers rely upon reflection, and although they work, they try to mimic what the middleware does.
Additionally, you may add controllers in different ways, and it is not rare to have the controllers shipped in multiple assemblies. In such cases, relying on reflection requires too much knowledge: for example, you have to know which assemblies are to be included, and when controllers are registered manually, you might choose a specific controller implementation, thus leaving out some legit controllers that would be picked up via reflection.
The proper way in ASP.NET Core to get the registered controllers (wherever they are) is to require this service IActionDescriptorCollectionProvider.
The ActionDescriptors property contains the list of all the actions available. Each ControllerActionDescriptor provides details
including names, types, routes, arguments and so on.
var adcp = app.Services.GetRequiredService<IActionDescriptorCollectionProvider>();
var descriptors = adcp.ActionDescriptors
.Items
.OfType<ControllerActionDescriptor>();
For further information, please see the MSDN documentation.