Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Implementing ApiVersion, working with constructor chaining for a different version format #990

TonicHess started this conversation in General
Discussion options

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?

You must be logged in to vote

Replies: 1 comment · 2 replies

Comment options

Parsing, formatting, and construction are all separate. An extended ApiVersion would likely start with this constructor:

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

public virtual string ToString( string? format, IFormatProvider? formatProvider )

From there, you should be able to replace or extend formatting as you see fit.

Start there and let me know how it goes.

You must be logged in to vote
2 replies
@TonicHess
Comment options

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?

@commonsensesoftware
Comment options

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.