I have a .NET project running in C# using WebApi 2.2.
I am registering all of my routes using attributes. What I would like to do is pro grammatically retrieve all of the attribute route templates as strings.
Something like: var routeTemplates = System.Web.Routing.RouteTable.Routes.Select(x => x.RouteTemplates);
I am able to see all of the the routes when I put a watch on ControllerContext.Configuration.Routes
However, I cannot seem to access the routes from my code as they are protected internals. How do I get at them?
I've attached a screen shot which shows the values I am seeing on my locals watch
that I need to get at.
When registering the attribute routes in Web API you can register a custom IDirectRouteProvider
to customize how attribute routes are found. In that custom IDirectRouteProvider
you can delegate all the "hard" work to the default implementation, DefaultDirectRouteProvider
, that looks at all the controllers and actions to compute the list of attribute routes, and then take credit for all that hard work.
To set this all up, first create a new "observable" direct route provider that delegates all its work:
public class ObservableDirectRouteProvider : IDirectRouteProvider
{
public IReadOnlyList<RouteEntry> DirectRoutes { get; private set; }
public IReadOnlyList<RouteEntry> GetDirectRoutes(HttpControllerDescriptor controllerDescriptor, IReadOnlyList<HttpActionDescriptor> actionDescriptors, IInlineConstraintResolver constraintResolver)
{
var realDirectRouteProvider = new DefaultDirectRouteProvider();
var directRoutes = realDirectRouteProvider.GetDirectRoutes(controllerDescriptor, actionDescriptors, constraintResolver);
// Store the routes in a property so that they can be retrieved later
DirectRoutes = DirectRoutes?.Union(directRoutes).ToList() ?? directRoutes;
return directRoutes;
}
}
And then use this new class from the WebApiConfig.Register
method in your app's startup:
public static class WebApiConfig
{
public static ObservableDirectRouteProvider GlobalObservableDirectRouteProvider = new ObservableDirectRouteProvider();
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes(GlobalObservableDirectRouteProvider);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Note that the data is ultimately stored in a static field. This is required because the code inside WebApiConfig.Register
is not called immediately - it's called later in global.asax.cs
. So, to observe the results of everything, add some code to Application_Start
:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
var allDirectRoutes = WebApiConfig.GlobalObservableDirectRouteProvider.DirectRoutes;
// now do something with 'allDirectRoutes'
}
And in a little test I wrote, I got these values:
And there you have it, a list of all the attribute routes in the app!
Note: There's additional data squirrelled away in the DataTokens
property of each route if you want to figure out where each attribute route came from.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With