-
Notifications
You must be signed in to change notification settings - Fork 712
Advice on integrating swagger via Swashbuckle #46
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
Comments
There have definitely been some thoughts and discussions about lighting that up, but there aren't any concrete plans just yet. It was actually on my mind in the earliest incarnations of this work a couple of years ago before Swagger was all the rave. With that in mind, it was important to make sure that the API version metadata doesn't solely rely on attributes and can be easily be retrieved by other components such as extension points. ApiVersionModel serviceApiModel = controllerDescriptor.GetApiVersionModel();
ApiVersionModel actionApiModel = actionDescriptor.GetApiVersionModel();
if ( !serviceModel.IsApiVersionNeutral )
{
foreach ( var version in serviceApiModel.SupportedApiVersions )
{
// TODO:
}
foreach ( var version in serviceApiModel.DeprecatedApiVersions )
{
// TODO:
}
} The collections of API versions have the following meanings:
As it happens, the design of ASP.NET Web API never accounted for the fact that there could be multiple implementations of a route. There is handling for duplicate routes by default, but this is assumed to be always be a developer mistake. This made supporting API versioning in Web API a bit of a challenge and sometimes wonky. Fortunately, the model is much better in ASP.NET Core. As a result of these assumptions, I had to introduce a special HttpControllerDescriptorGroup which aggregates all HttpControllerDescriptor for a service together. If you try to rely solely on the IHttpControllerSelector.GetControllerMapping method, it will make things a bit odd. In order for that to work, all of the similar controllers must have the same key, which there is no guarantee of. In addition, the API version aggregation work is only done at runtime because it's based off of the candidates the routing infrastructure provides. I've made all the related APIs and extensions methods public so you should be able to take advantage of them in one of a couple of ways: Option 1var controllerSelector = configuration.Services.GetHttpControllerSelector();
var versionMapping =
controllerSelector.GetControllerMapping()
.ToDictionary(
kvp => kvp.Key,
kvp =>
{
// this could be an HttpControllerDescriptorGroup
// which is enumerable. account for this without
// making a hard dependency on that type
var descriptors = kvp.Value as IEnumerable<HttpControllerDescriptor ??
new []{ kvp.Value };
return descriptors.Select( d => d.GetApiVersionModel() ).Aggregate();
} );
// TODO: use controller name to API version mapping Option 2var services = configuration.Services;
var assembliesResolver = services.GetAssembliesResolver();
var typeResolver = services.GetHttpControllerTypeResolver();
var controllerTypes = typeResolver.GetControllerTypes( assembliesResolver );
var controllerDescriptors = controllerTypes.Select( controllerType =>
new HttpControllerDescriptor(
configuration,
string.Empty,
controllerType ) );
// TODO: you need a way to logically group services together here.
// there's nothing out-of-the-box yet, but it will likely make sense
// at some point. maybe something like:
//
// [ApiServiceName( "HelloWorld" )]
IDictionary<string, List<HttpControllerDescriptor>> groupedControllerDescriptors = GroupControllersSomehow();
var versionMapping =
groupedControllerDescriptors.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value.Select( d => d.GetApiVersionModel() ).Aggregate() );
// TODO: use controller name to API version mapping Additional NotesWhen you inspect the API version model for actions, keep in mind that does not relate to routing or the version of the service. The API version for an action is only used for selecting which method to dispatch to when controllers have interleaved API versions. Don't interleave versions and things are much simpler. If you do want to support it, then just make sure you choose the action that has at least one explicitly matching, mapped API version. Actions cannot be version-neutral nor have deprecated versions. The DeclaredApiVersions property is probably the most useful here. Any action that does not have at least one explicitly mapped API version always implicitly matches the API version of the defining service (kind of like a method overload). That should be enough to get you started. Let me know if you have more questions. If you come up with something generic, please share. |
Nice amount of detail there, points me in the right direction. I'm glad I asked :) Thanks for the response. |
Is there a sample showing how to get this done? If not, would it be possible to add a really simple one in the project samples? |
For anyone else coming here. looks like built in support using ASP.NET Core's abstraction layer is coming soon in #60. If you need full support today, there is this thread domaindrivendev/Swashbuckle.AspNetCore#244 with a full blown NuGet package you can use called SwashbuckleAspNetVersioningShim. I think I'll be waiting for proper support. |
It is indeed coming. I just updated PR #103 with the alpha support for ASP.NET Core. I think I have most of the right abstractions and setup in place for most scenarios. I have a sample project up so you can see how things will wire up. You'll want to look at Startup.cs and ImplicitApiVersionParameter.cs. I'm avoiding any direct coupling on Swagger or Swashbuckle, which is why the ImplicitApiVersionParameter.cs is needed (unless I find an alternate way to include it). Fortunately, this class only requires minimal work to implement. It also varies greatly, depending on how you choose to implement API versioning. This might be better handled with a template or directly in Swashbuckle. While the API explorer work is meant to support Swagger and Swashbuckle, it could be used in other contexts as well. I'm definitely looking for feedback to make sure this is what the community has really been asking for. Thus far, I think it's really close. If you want to try it, feel free to pull the branch down. Thanks. |
Hi team, Thanks for the code above on versioning , but i am facing an issue with the below code, please help if i am missing out, 1.The swagger generated doesn't show the any information about the second method on the swagger/docs/v2 generated. [ApiVersion("1.0")]
} |
@Ramya5108 you have not defined the route parameter and constraint correctly. The value must be surrounded with In order to integrate with Swagger/Swashuckle, you'll want the appropriate corresponding API explorer package. The links, by platform, can be found in the API Documentation topic. It's worth noting that neither the API explorer nor Swashbuckle will translate your route template from For additional information and end-to-end working examples, I recommend you review the API Documentation topic. There are links to the samples by platform. |
Hi @commonsensesoftware , Thanks for the reponse , Sorry that i missed v{version:apiVersion}/hello in the sample above , while actual code had this. From the links you have provided , i understand that ordercontroller lied on 3 different namespaces for each version , to me i am looking for the same controller , same namespace , supporting multiple versions . As well , the samples on the link used swashbuckle .aspnetcore package and asp.net core application.While i use swashbuckle and asp.net web application. i agree that routetemplateparameter will be unaware of the value, Could you please help me with a link on the sample to tweak the swagger on this?is that possible? https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/244 am facing the same issue , while not with asp.net core application , but using asp.net web application.Please help @commonsensesoftware !! |
@Ramya5108, the wiki links provided have the setup instructions and required NuGet packages for all ASP.NET platforms, including Web API. There are numerous, numerous combinations in which you might compose your application to support mapping code to services and API versions. You might use different namespaces, you might not. Ultimately, the API versioning libraries don't care which approach you use. They are able to discover your APIs and their versions. If you examine the V1 OrdersController, you'll see that it implements versions Please review the complete end-to-end ASP.NET Web API with API Versioning and Swashbuckle sample. I hope that helps. |
Thanks @commonsensesoftware for your inputs |
I'm curious if there has been any attempts at connecting controllers that use this versioning scheme with Swagger/Swashbuckle? I thought I'd ask here since I can see this being used often in conjunction with those kinds of libraries.
I think I've got the version resolution sorted. Does this logic look correct for determining which actions to include per API version? or is there a better way....
but I wanted to get a list of versions discovered in the assembly, rather than manually defining them. Should I also loop over all the
ControllerDescriptor
s here as well, or is there a "discovered versions" registry somewhere (I couldn't find one.)Appreciate your thoughts here :)
PS: I haven't quite got a working version with
config.MapVersionedODataRoutes("odata", "odata", models);
, but it works happily if I use the built inconfig.MapODataServiceRoute("odata", "odata", models.First())
and pass in the first model only.The text was updated successfully, but these errors were encountered: