Swashbuckle.aspnetcore: Integrate better with Microsoft.AspNetCore.Mvc.Versioning

Created on 4 Apr 2017  路  8Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

If I decorate my controller with the following attributes:

[ApiVersion("1.0")]
[Route("v{version:apiVersion}/api/bla")]

I want Swashbuckle to generate documentation with paths that look like this:

"/v1.0/api/bla/foo"

And not this:

"/v{version}/api/bla/foo"
p3

Most helpful comment

As it relates to the original question - yes. The API Explorer options defined by API Versioning now (for a while) have the bool SubstituteApiVersionInUrl { get; set; } property, which when true will replace and remove the API version route parameter with the mapped API version value. The format of the API version can further be controlled by the string SubstitutionFormat { get; set; } = "VVV"; property, which formats the major version number and optional minor version (the most common variant). These behaviors only apply to the API Explorer and are useful for integration with tools such as Swashbuckle.

I believe this issue is now fully resolved. I hope that helps.

All 8 comments

Do you need to have a capital I for apiVersion, so that it matches the attribute?

No, it works like in my example. I'm actually not quite sure what you're asking.

There are solutions in this repo and in Versioning repo.
Versioning repo drives this process.

For now you can use this sample

@VictorGavrish the issue is that Swagger, API Versioning, and API explorers do not translate or evaluate route templates. Furthermore, I'm not sure that there is a way in the model metadata to say that a route parameter value is read-only. In some cases, a route parameter value might be read-only, but in others variable. For example, using the route template: /api/resources/{id}, you expect to be able to provide a value for {id}. The same is true for {version}. In some cases, you might have a 1:1 mapping, but it's also possible to have a 1:* mapping. I'm not sure how you would express when you can or can't provide a value for a route parameter value.

In the API Versioning examples, I show how to address this issue by provide a default value for the API version parameter, for each API version. I just submitted a PR (to myself for public visibility) that will make this process even easier. I've also discovered a couple of issues in Swagger (#412) and submitted PR #413 to resolve it. When both of these are merged and published, you'll be able to use API Versioning and Swagger out-of-the-box without using a IOperationFilter (at least not for API versioning information).

I don't think it's what you meant by the title of this issue, but there is a broader issue by which Swashbuckle dictates how API versioning must be done with respect to how the Swagger document is retrieved and the UI is browsed. This isn't unreasonable given there wasn't a _standard_ way to do this in the past. I've met with the ASP.NET team and some time in the not-too-distant future they'll be absorbing core abstractions (or more) from API Versioning. Once that happens, it should enable other extensions, such as Swashbuckle, to provide more options for how Swagger documents and UIs are accessed. I for one am not a fan of the API version in the URL path.

If I'm interpretating the following statement correctly ...

"Swashbuckle dictates how API versioning should be done"

It's not correct. It exposes an option __DocInclusionPredicate__ where you can fully customize the process of selecting actions for a document to align with whichever way you've implemented versioning. It's in the readme.

Thanks @domaindrivendev. I understand that you can customize how documents are matched to explored APIs, but that's not really what I was referring to. The DocInclusionPredicate was more useful to fill the gap for API versioning when an API explorer didn't exist - IMO. It's no longer necessary with API versioning; however, it's useful in other scenarios too.

What I was referring to is the incongruence between Swagger URLs and the service APIs. For example, if my services use URLs like /api/resources?api-version=1.0, the Swagger documents will still have the form of /swagger/v1.0/swagger.json. While there is some amount of customization that can be done with URLs and Swagger routing, it is somewhat limited. Ideally, the versioning methodologies of the APIs and Swagger documents would be identical. IMO that would provide better consistency and understanding for service clients.

My comment wasn't meant to be a criticism. If there are other ways to define the Swagger routes, feel free to educate me. If you're ever interested to exploring methods to increase the parity between Swagger routing and API versioning, we should chat. :)

As it relates to the original question - yes. The API Explorer options defined by API Versioning now (for a while) have the bool SubstituteApiVersionInUrl { get; set; } property, which when true will replace and remove the API version route parameter with the mapped API version value. The format of the API version can further be controlled by the string SubstitutionFormat { get; set; } = "VVV"; property, which formats the major version number and optional minor version (the most common variant). These behaviors only apply to the API Explorer and are useful for integration with tools such as Swashbuckle.

I believe this issue is now fully resolved. I hope that helps.

Was this page helpful?
0 / 5 - 0 ratings