-
Notifications
You must be signed in to change notification settings - Fork 714
-
Following the discussion here:
https://github.com/dotnet/aspnet-api-versioning/wiki/Custom-API-Version-Format
I'm looking for a clean way to implement the API version, while also supporting custom version strings.
The structure seems to lock in the idea of "Major.Minor-Status" as the string format, as those fields are immutable, and must be set through the constructor before any code for parsing the version can execute. It seems that I can do this with an external builder... is that the only way?
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 1 comment 2 replies
-
Parsing, formatting, and construction are all separate. An extended ApiVersion
would likely start with this constructor:
aspnet-api-versioning/src/Abstractions/src/Asp.Versioning.Abstractions/ApiVersion.cs
Line 98 in 2487953
The format is really more [Date.][Major.Minor]-[Status]
, which in totality doesn't make sense. You'd probably only reasonably have Date-Status
and Major.Minor-Status
, but you can use them all if you want to do. It's true that you can't remove the other pieces, but you don't have to use them (e.g. they can be null
). Exactly how to customize things, you'll likely need to override GetHashCode
and CompareTo
. The implementation Equals
just compares GetHashCode
. To customize formatting, you need to override
aspnet-api-versioning/src/Abstractions/src/Asp.Versioning.Abstractions/ApiVersion.cs
Line 341 in 2487953
From there, you should be able to replace or extend formatting as you see fit.
Start there and let me know how it goes.
Beta Was this translation helpful? Give feedback.
All reactions
-
I'm really trying to remove any of the date information, and get to a custom version string that isn't just [Major.Minor]-[Status]
... Ideally something like [token1].[token2].[token3]
, with a reserved shortcut for just [token]
(no major/minor/status stuff at all).
I think I've gotten the equals/hashcode stuff worked out, I'm just getting stuck on how to wire in the Provider/Formatter/Reader... the codepath bounces between all of them, and its tough to debug through to understand what's going on as there are so many partial classes :-/
Are there any examples of a successful custom version format?
Beta Was this translation helpful? Give feedback.
All reactions
-
It's not terribly complex, but there are a lot of moving parts. I don't know of anyone that has bothered to put in the full effort required to actually implement a custom API version. It's a bit dense for here so I created the following Gist:
https://gist.github.com/commonsensesoftware/e7280cc49381928b2297f1f4e5314c36
Once implemented, the setup would change to something like:
services.AddSingleton<IApiVersionParser>( CustomApiVersionParser.Default ); services.AddApiVersioning( options => { options.DefaultApiVersion = new CustomApiVersion( "*", "*" ); options.ReportApiVersions = true; } );
For a Minimal API, the configuration might be:
var forecast = app.NewVersionedApi(); // GET /weatherforecast?api-version=A.1 forecast.MapGet( "/weatherforecast", () => Results.Ok() ) .HasApiVersion( new CustomApiVersion( "A", "1" ) ); // ← built-in extension methods cannot be used here; create new ones
For a controller-based API, it would be more like:
[ApiVersion("A.1")] // ← parses using CustomApiVersionParser.Default [ApiVersion("B", "2")] // ← no parsing required [ApiController] [Route("[controller]")] public class WeatherForecastController : ControllerBase { [HttpGet] public IActionResult Get() => Ok(); }
I tested this out and if the built-in ApiVersion
is used, it no longer matches. Similarly, using ?api-version=A.1
or ?api-version=B.2
, matches as expected. You shouldn't need any custom readers. Formatting is optional and primarily useful for OpenAPI. I've given you a partial implementation, but you'd have to define your own format codes and how they are implemented. I hope that helps get you started.
Beta Was this translation helpful? Give feedback.