Skip to content

When doing MediaTypeApiVersioning with Swagger, application/json;v=1.0 returns 415 #164

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

Closed
ThomasCronholm opened this issue Jul 12, 2017 · 3 comments

Comments

@ThomasCronholm
Copy link

ThomasCronholm commented Jul 12, 2017

This is a question, do not know if it is a issue.

I am doing MediaTypeApiVersioning and when I enable swagger. When doing Put/Post with jason body I get a 415 for all except the "application/x-www-form-urlencoded" Content-Type. If I comment out the EnableSwagger part, everything works as it should.

I am using versioning v2.0.1 & apiExplorer v1.0.1.

This is the config for versioning and swagger that i am using.

// we only need to change the default constraint resolver for services that want urls with versioning like: ~/v{version}/{controller}
            var constraintResolver = new DefaultInlineConstraintResolver() { ConstraintMap = { ["apiVersion"] = typeof(ApiVersionRouteConstraint) } };

            // reporting api versions will return the headers "api-supported-versions" and "api-deprecated-versions"
            configuration.AddApiVersioning(options =>
            {
                options.ReportApiVersions = true;
                options.ApiVersionReader = new MediaTypeApiVersionReader();
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.ApiVersionSelector = new CurrentImplementationApiVersionSelector(options);
            });
            configuration.MapHttpAttributeRoutes(constraintResolver);

            // add the versioned IApiExplorer and capture the strongly-typed implementation (e.g. VersionedApiExplorer vs IApiExplorer)
            // note: the specified format code will format the version as "'v'major[.minor][-status]"
            var apiExplorer = configuration.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV");

            configuration.EnableSwagger(
                    "{apiVersion}/swagger",
                    swagger =>
                    {
                        // build a swagger document and endpoint for each discovered API version
                        swagger.MultipleApiVersions(
                            (apiDescription, version) => apiDescription.GetGroupName() == version,
                            info =>
                            {
                                foreach (var group in apiExplorer.ApiDescriptions)
                                {
                                    var description = "This is Project, configurator proxy service api.";

                                    if (group.IsDeprecated)
                                    {
                                        description += " This API version has been deprecated.";
                                    }

                                    info.Version(group.Name, $"Project Services {group.ApiVersion}")
                                        //.Contact(c => c.UserName("Contact UserName").UserEmail("somename@company.com"))
                                        .Description(description);
                                    //.License(l => l.UserName("MIT").Url("https://opensource.org/licenses/MIT"))
                                    //.TermsOfService("Shareware");
                                }
                            });

                        // add a custom operation...
                        swagger.OperationFilter<SwaggerDefaultValues>();

                        // integrate xml comments
                        swagger.IncludeXmlComments(XmlCommentsFilePath);

                    })
                .EnableSwaggerUi(swagger => swagger.EnableDiscoveryUrlSelector());

BR
Thomas Cronholm

@commonsensesoftware
Copy link
Collaborator

I'm not sure why you would be receiving 415. I have not been able to reproduce that - yet. I did, however, find a bug in the API explorer when versioning by media type. I've already updated and published version 1.0.2 of the API explorer package. You'll need that for the remainder of this solution to work.

In looking at the Swashbuckle source code, it seems that the ApiDescriptionExtensions class used for generating the values for the Operation.consumes and Operation.produces properties does not consider or use additional media type parameters. This will prevent things from working correctly for you.

I'm already in the process of coordinating with the owner of Swashbuckle to improve the use of information provided by the API explorer. I'll add this to the list. In the meantime, you'll have to add the following to the beginning of the SwaggerDefaultValues.cs operation filter that is provided in the example project:

operation.consumes = apiDescription.SupportedRequestBodyFormatters
                                   .Union( apiDescription.SupportedResponseFormatters )
                                   .SelectMany( formatter => formatter.SupportedMediaTypes )
                                   .Select( mediaType => mediaType.ToString() )
                                   .Distinct()
                                   .ToArray();
operation.produces = operation.consumes;

In most cases, the input and output media types are the same. Should you need or support differences, you can update this to suit your needs. Once you've applied this update, you should see the media types are correctly listed as:

  • API Version 1.0
    • application/json; v=1.0
    • text/json; v=1.0
  • API Version 2.0
    • application/json; v=2.0
    • text/json; v=2.0
  • ...

I was able to apply these changes to the example and have it work. Give all of this a go and let me know if you're still stuck. Thanks.

@ThomasCronholm
Copy link
Author

Thank you for the quick response!
I have updated, implemented your proposed fix, tested it and it fixes the problem.
Your bug fix also fixes a second problem that was my next question to you!
So two birds with one stone!

Once again thank you!

@commonsensesoftware
Copy link
Collaborator

Glad to hear it. I've submitted a couple issues and a PR to use additional information I provide via the IApiExplorer. That should supplant the need for a custom IOperationFilter. Until then, the solutions here should work. I'll update the examples once that change is in place and available.

Feel free to come back if you have more questions or reopen open this issue if it's not resolved. Thanks!

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