-
Notifications
You must be signed in to change notification settings - Fork 708
Known Limitations
This only applies to versions >= 1.1.0 and <= 1.2.0
The routing mechanism in ASP.NET Core uses a series of routers in a Chain of Responsibility. In 1.1.x versions, the API versioning support for ASP.NET Core requires a new configuration step in order to register an additional API version-aware router into the pipeline using the UseApiVersioning extension method for the IApplicationBuilder interface. The order in which the router-related extensions are called are critical. If they are called in the wrong order, things may not behave correctly. This is particularly true if you are using the Single Page Application (SPA) JavaScript Services extensions.
The following configuration demonstrates how to include the SPA extensions with API versioning:
public void Configure( IApplicationBuilder app )
{
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=About}");
});
app.UseApiVersioning();
// note: this MUST be called last; exclude "api" routes for good measure
app.MapWhen( x => !x.Request.Path.Value.StartsWith( "/api" ), builder =>
{
builder.UseMvc( routes =>
{
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" } );
} );
} );
}
A similar configuration may be required for your scenario. For a lengthy discussion on why things must be setup and behave this way, please refer to Issue #146.
Prior to version 7.4.0, OData on ASP.NET Core uses the legacy routing system based on IRouter and does not support Endpoint Routing. To use ASP.NET Core 2.2 or above with an OData version less than 7.4.0, you must configure your application to disable Endpoint Routing:
services.AddMvc( options => options.EnableEndpointRouting = false );
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 provide 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