Search code examples
c#asp.net-web-api2attributerouting

RoutePrefix Order alternative for WebAPI 2


In WebAPI you can specify an Order in RouteAttribute to determine which order the routes are matched in. For example the below will match /other to GetOther before matching /blah to GetByName

[HttpGet, Route("{name}", Order = 1)]
public string GetByName(string name) { ... }

[HttpGet, Route("other")]
public string GetOther() { ... }

How would I do the same but with RoutePrefix (which doesn't have an Order property)? If it did it would looks something like this:

[RoutePrefix("foo", Order = 1)]
public class FooController : ApiController { ... }

[RoutePrefix("foo/bar")]
public class FooBarController : ApiController { ... }

Doing the above (without the imaginary Order property) throws the following message when calling /foo/bar:

Multiple controller types were found that match the URL

Is there existing functionality for getting around this (preferably with attributes)?


Solution

  • I don't believe Microsoft's attribute routing has support for ordering routes by controller.

    When you specify an Order property on an action's RouteAttribute, you are specifying the order within the controller only.

    AFAIK, the attribute routing algorithm will scan all of the controllers alphabetically. Then within each controller, is will use the Order property of any RouteAttributes to decide the order of action routes within that controller.

    This means if you have route collisions spread across different controllers, you should either rethink the design or make sure the controllers with the more specific route patterns are named alphabetically before the controllers with the more general route patterns. Otherwise, you may run into that "ambiguous route / multiple actions with matching routes found" exception.

    Update: The answer above is for Microsoft's AttributeRouting implementation, which was based on another very popular open source project that came before MVC5. In that library, you could order attribute routes by controller, though I think the property was SiteOrder or something like that.