-
Notifications
You must be signed in to change notification settings - Fork 704
Known Limitations
The Direct Route routing mechanism (aka attribute routing) in ASP.NET Web API was bolted onto the existing routing infrastructure. The design of the out-of-the-box router does not account for nor support overlapping routes between convention-based and attribute-based routes. The result of this behavior is that for each given route, all of the versioned controllers must use convention-based or attribute-based routes. Mixing the two routing strategies for the same route is not guaranteed to resolve correctly.
While it would be ideal to implement a router that could support both approaches, the level of effort to achieve this is high. Furthermore, it's significantly easier to rationalize about versioned controllers from a service author's perspective if all of the versioned routes follow the same routing strategy.
The OData support for ASP.NET Web API uses convention-based routing under the hood. If you want to support transitioning to, or from, OData using API versioning, your ApiController types that match the same routes must also use convention-based routing.
API versioning does not fundamentally change how routing works in ASP.NET. When you elect to support API versioning via a URL path segment, the API version is part of the path considered in routing. There is currently no built-in method to match a route where the API version URL path segment has not be specified.
The recommended method to enable this scenario is to use Double Route Registration by providing multiple routes for the corresponding controller actions as follows:
[ApiVersion( 1.0)]
[RoutePrefix( "api" )]
public class ValuesController : ApiController
{
// ~/api/values
// ~/api/v1/values
[Route( "values" )]
[Route( "v{version:apiVersion}/values" )]
public IHttpActionResult Get() => Ok();
}
[ApiVersion( 2.0 )]
[RoutePrefix( "api" )]
public class Values2Controller : ApiController
{
// ~/api/v2/values
[Route( "v{version:apiVersion}/values" )]
public IHttpActionResult Get() => Ok();
}
[ApiVersion( 1.0 )]
[ApiController]
[Route( "api/[controller]" )]
[Route( "api/v{version:apiVersion}/[controller]" )]
public class ValuesController : ControllerBase
{
// ~/api/values
// ~/api/v1/values
[HttpGet]
public IHttpActionResult Get() => Ok();
}
[ApiVersion( 2.0 )]
[ApiController]
[Route( "api/v{version:apiVersion}/values" )]
public class Values2Controller : ControllerBase
{
// ~/api/v2/values
[HttpGet]
public IHttpActionResult Get() => Ok();
}
If you're using ASP.NET Web API, you can also choose to implement a custom IDirectRouteProvider as suggested in Issue #73.
If you're using ASP.NET Core, you can use middleware or other customizations to simplify your implementation. This Gist post provides one such implementation that allows URL versioning to external clients, but allows simplified URL mapping internally. For example, api/v1/values
becomes api/values
internally, captures the 1.0
API version, and sets the requested API version via the IApiVersioningFeature.
- Home
- Quick Starts
- Version Format
- Version Discovery
- Version Policies
- How to Version Your Service
- API Versioning with OData
- Configuring Your Application
- Error Responses
- API Documentation
- Extensions and Customizations
- Known Limitations
- FAQ
- Examples