-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Epic: Improve API version support #1355
Comments
I just stumbled across a number of posts and issues that all seem to lead back to here. The implementation of ApiVersionProcessor.cs is not correct and will miss many scenarios. API Versioning does not actually care about attributes and that is only one way that API versions can be provided. API versions can also be provided by conventions or through custom extensions. The API Explorer extensions provided by API Versioning already does all of the difficult work of collating API descriptions by API version so they can be integrated with other libraries such as Swagger generators like NSwag. Things already work well with Swashbuckle without any cross-dependencies or understanding of what each library does. I would be curious and interested in understanding why the same model doesn't work for NSwag. I'm open to discussing how the integration can be made better. |
@commonsensesoftware you are right, we should remove the ApiVersionProcessor completely and only rely on the grouping in the versioned API Explorer... this way it should just work. I never used this in a project this is why it's not really correctly implemented. |
No problem. It was less of a critique and more of "Hey, is something not working right?". In working with Swashbuckle, we uncovered a design flaw/omission in the ASP.NET Core API Explorer design. You'll want to take a peek at: aspnet/Mvc#7563. The ASP.NET team has made the necessary adjustments, but it won't be available until 2.2. This may affect your backward compatibility story. At a minimum, it should help explain what can or cannot be mapped. The documentation is pretty thin in this area and I was left scratching my head for quite a while. There's a pretty long thread in Swashbuckle on this topic too. Effectively, we agreed that ASP.NET Core has this gap (which is how we got them to change it) and we shouldn't make any special workarounds. Once the change is available, API Versioning will populate the correct explored values and consumers like NSwag, Swashbuckle, etc can consume it. Should you run into any issues. Feel free to reach out. |
@commonsensesoftware just checked this, if you use AddVersionedApiExplorer: And specify the included versions as shown here (i.e. a api group name filter): It just filters by api group name and removes {version} from the route (if available): No other reflection hacks (as i see it). But maybe it would be still good to add a ApiGroup setting to AspNetCoreToSwaggerSettings so that we can filter by api group directly (but then the {version} removal is missing if the processor is not added). |
If a service author is versioning by URL segment and they don't want the route parameter or API parameter desciption included, they just need to specify that in the API explorer options a la: AddVersionedApiExplorer( options => options.SubstituteApiVersionInUrl = true ); This removes all API version parameters and substitutes the route parameter with a value formatted according to the It's also worth noting that the apiVersion route constraint key is configurable starting in API Versioning 3.0+ via |
Ok so my proposal
This way its fully controlled by the api explorer. What do you think? |
That sounds right to me. I don't mind if you do double-work, but I figure you don't want to support external idiosyncrasies if you don't have to. ;) Honestly, I'm not super familiar with the particulars of NSwag. I know things are similar to Swashbuckle. Obviously, I know the API Explorer very well. If you haven't seen the sample project I provide, it might be worth giving it a once over for ideas that might influence the integration points of your design. You won't see much of anything related directly to the API Explorer. The I also provide a custom IApiVersionDescriptionProvider. You see this service used in the example. The purpose of this service is to distinctly enumerate all possible API versions with their group name and indicate whether they are deprecated. API descriptions and so on are not provided by this collection. There are many possible use cases for this service, but a common scenario is enumerating the results to produce a Swagger document for each API version. The provided group name can be used to match up against the group name defined in API descriptions. For service authors that want to omit or otherwise call out deprecated API versions, that information is provided so they don't have to figure it out. Naturally, you don't want any dependencies on any of that. However, hopefully that puts some context around how things are meant to work and they have worked together with other libraries such as Swashbuckle thus far. The integration from your standpoint is supposed to be easy so you can focus on what you do best - generating Swagger. :) |
I completely agree with you - and I want to reuse as much as possible of this logic and not implement it in NSwag. This processor comes from the times when everything was reflection based and I think the api versioning package didnt have api explorer support back then... The goal is to remove this feature in a way that breaking users get a good notification how to fix it/change it for the new way... |
@commonsensesoftware I created a PR based on our discussion: #1701 |
Other than the broken tests, it looks pretty good. I just realized that you support Web API too. I have similar support for grouping in Web API, but due its limited API Explorer design, it doesn't surface in a library-sharable manner. You'll have to pardon my ignorance because I don't know how NSwag bridges this gap. In Swashbuckle, they used a callback function. The API Versioning API Explorer for Web API provides an extension method to get the corresponding group name, which is expected to match the format of the Swagger document version. This has the callback form ( apiDescription, version ) => apiDescription.GetGroupName() == version You can see the full Web API example here. Beyond something like a callback function, I'm not sure how you can marry the two sides without some type of dependency. If you were content with using Reflection or dynamic dispatching, this is probably the one and only place were it might make sense. I had to do a bunch of my own hackery to make the Web API IApiExplorer work because a significant part of the default implementation relies on internal types and methods. If you were going to support such a concept, it might look something like the implementation of the GetGroupName extension method. The only difference in your case would be testing for the presence of a property named GroupName on the ApiDescription. This would bridge the gap for API Versioning and any other IApiExplorer implementation that happens to return ApiDescription instances with a GroupName property. I doubt we'll ever see things changed in Web API. These are the best ideas I can think of. I leave it up to you as to which route you think is appropriate for NSwag consumers. |
The web api generator is deprecated and i dont have the capacity to work on this at the moment... |
Will fix the tests soon |
Ah … gotcha. I thought I saw changes related to Web API. It caught my attention so I thought I'd mention it. If you ever decide to revisit it at a later point, I'm happy to discuss the integration points. |
Issues:
The text was updated successfully, but these errors were encountered: