Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize MapHttpAttributeRoutes for Web Api Versioning

I am implementing Web API versioning as in Web API Versioning. My controllers are in 2 separate namespaces, and I've used a custom SelectController method to choose which version to use based on a a query parameter. e.g.

http://myapi/api/values?version=1.0

This all works fine but some actions in the controllers use the Route attribute

[Route("api/values/getNames")]
public HttpResponseMessage Get() { ... }

Which are mapped to the correct controller by default using

config.MapHttpAttributeRoutes();

in WebApiConfig.cs

This will not work if I have multiple versions of the API with the same route. Am I able to provide a custom implementation for config.MapHttpAttributeRoutes() so I can select the correct version of the API to use, or is there a better way of doing this?

like image 817
nickela125 Avatar asked Dec 02 '22 15:12

nickela125


1 Answers

There is an example for this in the official WebApi 2.1 examplex on Codeplex. It relies on a request header value to store the version.

I think it's a lot nicer, since it allows the routes to stay the same for all versions. Clients select the version simply by including an HTTP header in the request (in this case the version number).

This sample shows how to use Attribute Routing and Constraints in ASP.NET Web API to dynamically filter controllers by an 'api-version' HTTP header. When a route uses Constraints, each constraint has a chance to prevent the route from matching a given request. In this sample, a custom RouteFactoryAttribute (VersionedRoute) adds a constraint to each attribute route.

...

The custom constraint implementation (VersionConstraint) is implemented based on the value of 'api-version' matching an integer value. The value of the allowed version for the constraint is provided by the VersionedRoute attribute placed on each controller. When a request comes in, the header value of 'api-version' is matched against the expected version. This example uses a header but a constraint implementation could use any criteria to decided if the request is valid for the route.

Anyway, the end result would end up looking like this:

[VersionedRoute("api/Customer", 1)]
public class CustomerVersion1Controller : ApiController
{
    // controller code goes here
}
[VersionedRoute("api/Customer", 2)]
public class CustomerVersion2Controller : ApiController
{
    // controller code goes here
}
like image 99
Marcel N. Avatar answered Dec 10 '22 18:12

Marcel N.