Skip to content
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

"No operation defined in spec" when using NSwag and AddVersionedApiExplorer #570

Closed
andreborgesdev opened this issue Oct 29, 2019 · 3 comments

Comments

@andreborgesdev
Copy link

Whenever I try to use AddVersionedApiExplorer to force my API version so I don't have to type it, as it is considered an required parameter because it is passed on the URL, I get an "No operation defined in spec". I already tried to debug to see if the problem was in the APIVersion annotation on the Controller but everything is fine there. Bellow I demonstrate the different behaviors I get without and with AddVersionedApiExplorer.

Without AddVersionedApiExplorer

        protected virtual void AddApiVersioning(IServiceCollection services)
        {
            services
                .AddApiVersioning(options =>
                        {
                            options.AssumeDefaultVersionWhenUnspecified = true;
                            options.DefaultApiVersion = new ApiVersion(
                                                            Primavera.Lithium.Sample.Models.Metadata.ApiVersions.DefaultVersion.Major, 0);
                            options.ReportApiVersions = true;
                        });
        }

Working Documentation

With AddVersionedApiExplorer

        protected virtual void AddApiVersioning(IServiceCollection services)
        {
            services
                .AddApiVersioning(options =>
                        {
                            options.AssumeDefaultVersionWhenUnspecified = true;
                            options.DefaultApiVersion = new ApiVersion(
                                                            Primavera.Lithium.Sample.Models.Metadata.ApiVersions.DefaultVersion.Major, 0);
                            options.ReportApiVersions = true;
                        });

            services.AddVersionedApiExplorer(options => options.SubstituteApiVersionInUrl = true);
        }

Not working Documentation

I'm using an internal SDK that generates the API from a .lsm model, however I already checked and it doesn't seem to be from there.

@commonsensesoftware
Copy link
Collaborator

You can be almost guaranteed that it will not work without the API Versioning API Explorer extensions enabled via services.AddVersionedApiExplorer(). If it somehow magically works, it's specific to NSwag.

I'm not all that familiar with NSwag, but since it started with similar roots to Swashbuckle, I'm willing to bet that the matching of groups to Swagger/OpenAPI documents is the same. Remember that the API documentation Group Name is not the same as the actual API Version. Furthermore, I see that the group name in the drop down is v1, but the character v is never part of the API Version.

To make the API Version match the Group Name the way you want, you have to specify the format to use. The default doesn't include the v because it would be specific to this particular style of versioning. A drop down with 1.0, 2.0, 11-01-2019, and so on are all perfectly valid and reasonable. This is almost certainly why you get no specs because the text between the two don't match up.

The following excerpt from the examples demonstrates how to match the two up:

services.AddVersionedApiExplorer(
  options =>
  {
    options.GroupNameFormat = "'v'VVV";
    options.SubstituteApiVersionInUrl = true;
  } );

This will result in the API Version 1.0 being formatted as v1 for the ApiDescription.GroupName property, which should be how NSwag is connecting the two.

You can also use the IApiVersionDescriptionProvider service to enumerate all of the API versions in your application. Every ApiVersionDescription includes the real API version, the formatted group name, and indicates whether the API version is deprecated (e.g. all actions are marked as such).

For Swashbuckle, it would look like this. I suspect that it's not that different for NSwag.

foreach ( var description in provider.ApiVersionDescriptions )
{
  var url = $"/swagger/{description.GroupName}/swagger.json";
  var name = description.GroupName.ToUpperInvariant();
  options.SwaggerEndpoint( url, name );
}

I hope that helps.

@andreborgesdev
Copy link
Author

I really tried everything but nothing worked I really can not figure out why, so I just upgraded my app to .NET Core 3.0 and now it works perfectly for some reason.

However I still need to add AddVersionedApiExplorer otherwise with only AddApiVersioning my API is not able to detect the version I'm using, for some reason.

services.AddVersionedApiExplorer(options => options.SubstituteApiVersionInUrl = true);

Thank you very much for the help :)

@commonsensesoftware
Copy link
Collaborator

You'll always have to add service.AddVersionedApiExplorer because that's what provides the extensions to make the API Explorer API version-aware. Specifically it does all the discovery and collation of actions by API version.

You didn't mention which version of NSwag you were using, but if it's a really recent version, I suspect that it may followed some of the same changes as Swashbuckle. You may have been hit by the same bug in #562

Regardless, I'm glad you got it working. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants