Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

get a list of attribute route templates asp.net webapi 2.2

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.

The data I want to get at

like image 946
Ray Suelzer Avatar asked Mar 30 '15 01:03

Ray Suelzer


1 Answers

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:

enter image description here

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.

like image 77
Eilon Avatar answered Oct 15 '22 04:10

Eilon