mayabelle
mayabelle

Reputation: 10014

Web API Help Pages - Order controllers by route prefix

Since areas are not easily supported in Web API (and also because I need more flexibility than project-wide routing rules), I am using the [RoutePrefix] attribute on my controllers to group my Web API controllers into namespaces, e.g.:

[RoutePrefix["Namespace1/Controller1"]
public class Controller1 : ApiControllerBase { }

[RoutePrefix["Namespace1/Controller2"]
public class Controller2 : ApiControllerBase { }

[RoutePrefix["Namespace1/Controller3"]
public class Controller3 : ApiControllerBase { }

[RoutePrefix["Namespace2/Controller4"]
public class Controller4 : ApiControllerBase { }

[RoutePrefix["Namespace2/Controller5"]
public class Controller5 : ApiControllerBase { }

[RoutePrefix["Namespace2/Controller6"]
public class Controller6 : ApiControllerBase { }

(These are in separate files and contain actions within them, I just removed that, along with actual names, for simplicity.)

I am generating help documentation using Web API Help Pages, which works fine. However, I would like to group and order the documentation by my "namespaces" (group by route prefix, then sort alphabetically within each).

I decided to start out by just ordering and then figure out the grouping once I get the ordering to work. To get the ordering to work, I tried altering my Index.cshtml [in the HelpPage area created by the Web API Help Page Nuget package] from this:

@foreach (IGrouping<HttpControllerDescriptor, ApiDescription> group in apiGroups)
{
    @Html.DisplayFor(m => group, "ApiGroup")
}

to this:

@foreach (IGrouping<HttpControllerDescriptor, ApiDescription> group 
    in apiGroups.OrderBy(g => g.Key.GetCustomAttributes<RoutePrefixAttribute>().FirstOrDefault().Prefix)
                .ThenBy(g => g.Key.ControllerName))
{
    @Html.DisplayFor(m => group, "ApiGroup")
}

However, I get a null reference exception: in the LINQ expression above, g.Key.GetCustomAttributes<RoutePrefixAttribute>().FirstOrDefault() is null for all my controllers. This doesn't make any sense to me because the routing itself is working correctly (including the prefix). Any suggestions?

Upvotes: 4

Views: 3868

Answers (2)

Todd
Todd

Reputation: 13183

To elaborate on the answer from chris, I was able to get it working with the following code block. I am using Web API 2.2 (version 5.1.2)

@foreach (IGrouping<HttpControllerDescriptor, ApiDescription> group in apiGroups
    .OrderBy(g => g.Key.ControllerType.GetCustomAttributes<System.Web.Http.RoutePrefixAttribute>().FirstOrDefault().Prefix)
    .ThenBy(g => g.Key.ControllerName))
{
    @Html.DisplayFor(m => group, "ApiGroup")
}

You'll need to add

@using System.Reflection

to the top of the file in order to get the generic GetCustomAttributes extension method into scope.

Upvotes: 2

chris
chris

Reputation: 2621

Had the same issue recently ... there is a minor error in your LINQ expression.

apiGroups.OrderBy(g => g.Key.GetCustomAttributes<RoutePrefixAttribute>().FirstOrDefault().Prefix)

should read:

apiGroups.OrderBy(g => g.Key.ControllerType.GetCustomAttributes<RoutePrefixAttribute>().FirstOrDefault().Prefix)

This works for me, anyway.

Upvotes: 2

Related Questions