Comments (2)
There are a couple of different issues going on here so let me try to break up the response into pieces.
URL Path Versioning
When you version your API in the URL path, you can't logically have a default version. The API version is instrinsically part of the path. In your example, you have the route template api/{version:apiVersion}/Uri
. If an API version is not specified using this method, the URL becomes api//Uri
.
Most service authors that use URL path versioning prefix the API version segment value with the letter 'v'. This would make the route template api/v{version:apiVersion}/Uri
. Now, if an API version isn't specified, the path will become api/v/Uri
. I think it's pretty obvious that this won't exist.
The method in which the requested API version is internally set is - ever so slightly - different that any other method. All other methods go through the IApiVersionReader to extract the API version from the incoming request message. Trying to understand and parse the URL path in the same manner would be difficult and brittle. Since ASP.NET already provides a structured way to parse route templates, URL path versioning uses a route constraint instead. This allows you to craft your URLs however you want and just indicate which segment the API version should be extracted from.
You can use the route template as you defined it, but there is no way to assume a default because there are no matching candidates.
Default Version Selection
It may not be intrinsically obvious, but the DefaultApiVersion and ApiVersionSelector options are somewhat mutually exclusive. The purpose of the DefaultApiVersion is to simply define an assumed version without hard-coding the value for all fallback cases because every service always has some logical version number, even if it's not formally defined. The IApiVersionSelector is the extension point to select the appropriate API version given a request and the discovered API version model. The infrastructure does all the hard work of collecting the available API versions and you select the best one.
In your case, you elected to use the CurrentImplementationApiVersionSelector and have the following API versions defined:
- 1.0 (implemented, but deprecated)
- 2.0
- 3.0
This selector will always choose 3.0 from these choices. The only time it would ever use the default configured API version of 2.0 is if there were no candidate API versions to select from. For example, if your versions were all pre-release:
- 1.0-alpha
- 2.0-beta
- 3.0-rc
Any version with a status is not considered implemented. Additionally, deprecated does not mean not implemented.
If your intent was to have all clients that don't request a version start on 2.0, then you can just set the DefaultApiVersion. The default value for the ApiVersionSelector is an instance of the DefaultApiVersionSelector, which just always uses the value of the configured DefaultApiVersion.
Faking a Default API Version with URL Paths
There is one way that you can give the impression of an implicitly-version URL path. To enable this, you need to make multiple routes per controller. API versioning stays out of the way of routing and only gets involved with resolving the appropriate controllers and actions.
For example, if your controllers were updated with additional routes:
[ApiVersion( "1.0", Deprecated = true )]
[Route( "api/uri" )]
[Route( "api/{version:apiVersion}/uri" )]
public class UriController : ApiController { /* ommitted */ }
[ApiVersion( "2.0" )]
[Route( "api/uri" )]
[Route( "api/{version:apiVersion}/uri" )]
public class Uri2Controller : ApiController { /* ommitted */ }
[ApiVersion( "3.0" )]
[Route( "api/uri" )]
[Route( "api/{version:apiVersion}/uri" )]
public class Uri3Controller : ApiController { /* ommitted */ }
Your controllers will be resolved using the following URLs:
URL | Version | Controller |
---|---|---|
api/uri | 3.0 | Uri3Controller |
api/1/uri | 1.0 | UriController |
api/2/uri | 2.0 | Uri2Controller |
api/3/uri | 3.0 | Uri3Controller |
api/uri?api-version=1.0 | 1.0 | UriController |
api/uri?api-version=2.0 | 2.0 | Uri2Controller |
api/uri?api-version=3.0 | 3.0 | Uri3Controller |
The last 3 entries are there because the default configuration uses an IApiVersionReader that extracts the API version from the api-version query string parameter. If you want to remove this behavior, you can implement a reader that always returns null.
public class IgnoreApiVersionReader : IApiVersionReader
{
public string Read( HttpRequestMessage request ) => null;
}
You may have noticed that the example used the names UriController, Uri2Controller, and Uri3Controller. In setting up an example that would simulate your scenario, I found an edge case bug. I'll create a new issue for this bug and correlate it back to this thread. For now, using different type names will make this setup work.
I hope that helps.
from aspnet-api-versioning.
You well explained the problem with URL path versioning and DefaultApiVersion. Multiple routes on controller makes it bit confusing so i'm considering to choose e.g Custom Header versioning as this one fits better my scenario. Anyway thanks a lot for answer and solution. Cheers!
from aspnet-api-versioning.
Related Issues (20)
- ASP.NET Web API versioning Migrate from QueryStringApiVersionReader to UrlSegmentApiVersionReader HOT 2
- only the 5.1.0 version of Microsoft.AspNetCore.Mvc.Versioning is deprecated HOT 3
- Problem with describing reponse codes in minimal api HOT 3
- Cannot run APIs with different controller names with same ControllerName attribute after migration HOT 6
- Different options in `ApiVersioningOptions.cs` between .NET Framework and .NET Core packages HOT 2
- WithOpenApi() ignore Api versioning readers HOT 4
- .net 8 support HOT 7
- Breaking changes when migrating to OData8 + new versioning HOT 10
- odata/$metadata returns 404 when all controllers are decorated with ApiVersionNeutralAttribute HOT 3
- AddVersionedApiExplorer not working in Asp.Versioning HOT 5
- VersionedApiDescriptionProvider does not set the correct SunsetPolicy to ApiDescription instances HOT 1
- Using ApiExplorerSettingsAttribute together with ApiVersionAttribute produces unexpected number of ApiVersionDescriptions HOT 5
- Asp.Net Core WebApi - AWS ECS Cluster Authentication failure HOT 2
- [Versioned Clients][API Notifications] Fails to read new versions when available HOT 2
- Swashbuckle documentation inconsistent with examples HOT 2
- AssumeDefaultVersionWhenUnspecified does not work correctly if ApiVersionNeutral is used in the controller HOT 2
- swagger.json file not found after update HOT 9
- My API is not displaying all the versions. HOT 4
- Improve docs for HeaderApiVersionReader
- Add synonym to `AddMvc` method. HOT 7
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aspnet-api-versioning.