Swashbuckle.AspNetCore icon indicating copy to clipboard operation
Swashbuckle.AspNetCore copied to clipboard

Support content type from ProducesResponseTypeAttribute

Open drphrozen opened this issue 3 years ago • 7 comments

Using version 6.2.3

I have been trying to set the response type of one of my endpoints to "application/pdf". It works, sort of, when using the ProducesAttribute, like in the documentation, but adding another response type like 400 = application/json is not easy.

I would like to be able to use ProducesResponseTypeAttribute instead and it looks as if it follows the features as SwaggerResponseAttribute.

However, it seems the content-type from ProducesResponseTypeAttribute is not used in the schema:

// Works! content-type set to application/pdf
[SwaggerResponse(200, null, typeof(FileResult), "application/pdf")]
// Doesnt work content-type not set to application/pdf
[ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK, "application/pdf")]

drphrozen avatar Jan 25 '22 21:01 drphrozen

image image

It looks like it should be possible to get the content-type per status code.

I also just realized that when i define any content-type in the ProducesResponseType then the schema only contains the description and not the content: Output of [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK, "application/pdf")]

"responses": {
  "200": {
    "description": "Success"
  },
  "400": {
    "description": "Bad Request"
  }
}

Output of [ProducesResponseType(typeof(FileResult), StatusCodes.Status200OK)]

"responses": {
  "200": {
    "description": "Success",
    "content": {
      "text/plain": {
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WeatherForecast"
          }
        }
      },
      "application/json": {
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WeatherForecast"
          }
        }
      },
      "text/json": {
        "schema": {
          "type": "array",
          "items": {
            "$ref": "#/components/schemas/WeatherForecast"
          }
        }
      }
    }
  },
  "400": {
    "description": "Bad Request",
    "content": {
      "text/plain": {
        "schema": {
          "type": "string",
          "format": "binary"
        }
      },
      "application/json": {
        "schema": {
          "type": "string",
          "format": "binary"
        }
      },
      "text/json": {
        "schema": {
          "type": "string",
          "format": "binary"
        }
      }
    }
  }
}

drphrozen avatar Jan 26 '22 10:01 drphrozen

There is also a bug caused by this: When specifying a content type, the response type is ignored.

For these attributes:

[ProducesResponseType(200)]
[ProducesResponseType(typeof(ValidationProblemDetails), 400, "application/problem+json")]

The result is: ss1

And for these attributes:

[ProducesResponseType(200)]
[ProducesResponseType(typeof(ValidationProblemDetails), 400)]

The result is: ss2

OronDF343 avatar Feb 21 '22 09:02 OronDF343

I also bumped into this and use the SwaggerResponse workaround. This has been reported again in #2386.

rvdginste avatar Apr 23 '22 12:04 rvdginste

I did notice that the implementation of ProducesResponseType only accepts the content-type parameter since .net 6.0, and the attribute does not make the supplied parameters publicly available. There is a property, but it is marked internal with a comment that it is meant for testing purposes(see here). But I don't know whether Swashbuckle needs to access these attributes directly.

rvdginste avatar Apr 23 '22 12:04 rvdginste

I also encountered this issue. Swashbuckle leverages on ApiExplorer and not directly on the attribute. From what I see, the generator requires the ModelMetadata to be populated https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/src/Swashbuckle.AspNetCore.SwaggerGen/SwaggerGenerator/SwaggerGenerator.cs#L454 but it isn't the case when a content-type is provided in the ProducesResponseType attribute cause of the apiResponse.ApiResponseFormats being pre-populated https://github.com/dotnet/aspnetcore/blob/main/src/Mvc/Mvc.ApiExplorer/src/ApiResponseTypeProvider.cs#L207.

I'm not sure if it's an intended behavior on aspnetcore side but I think Swashbuckle can fallback on the ApiResponseType.Type property when ModelMetadata is null.

gcurb avatar Apr 29 '22 06:04 gcurb

I'm noticing this too. In version 6.5.0. With the following attributes:

	[HttpGet("{id}", Name = "GetAppointmentRequest")]
	[SwaggerResponse(StatusCodes.Status404NotFound, null, typeof(ProblemDetails), "application/problem+json")]
	[ProducesResponseType(typeof(AppointmentRequestDto), StatusCodes.Status200OK, MediaTypeNames.Application.Json)]

ASP.NET Core produces the right content-type, but the generated OpenAPI doesn't reflect what ASP.NET is doing.

image

If I include ProducesResponseType for the 404:

	[HttpGet("{id}", Name = "GetAppointmentRequest")]
	[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound, "application/problem+json")]
	[SwaggerResponse(StatusCodes.Status404NotFound, null, typeof(ProblemDetails), "application/problem+json")]
	[ProducesResponseType(typeof(AppointmentRequestDto), StatusCodes.Status200OK, MediaTypeNames.Application.Json)]

the OpenAPI has even less detail:

image

peteraritchie avatar Jun 26 '23 19:06 peteraritchie

I am facing the same bug. I cannot make proper swagger for FileStreamResult endpoint in version 6.5

qub1n avatar Nov 06 '23 15:11 qub1n