Skip to content

.NET 9 OpenAPI doesn't support [Consumes] multiple content types correctly. #58329

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

Open
1 task done
ascott18 opened this issue Oct 9, 2024 · 1 comment · May be fixed by #61401
Open
1 task done

.NET 9 OpenAPI doesn't support [Consumes] multiple content types correctly. #58329

ascott18 opened this issue Oct 9, 2024 · 1 comment · May be fixed by #61401
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi

Comments

@ascott18
Copy link
Contributor

ascott18 commented Oct 9, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Routes that accept both form and json bodies through multiple controller actions with [ConsumesAttribute], a documented, supported use case of aspnetcore, are not emitted correctly by Microsoft.AspNetCore.OpenApi.

The comment on these lines is incorrect:

// If there are no body parameters, check for form parameters.
// Note: Form parameters and body parameters cannot exist simultaneously
// in the same endpoint.
. It contradicts the documentation for [ConsumesAttribute] - https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-9.0#define-supported-request-content-types-with-the-consumes-attribute-1. A single route can indeed support both formdata and json bodies.

Expected Behavior

Both JSON and form content types are listed for the endpoint in requestBody.content in the OpenAPI document.

Steps To Reproduce

Write the exact example from the [Consumes] documentation at https://learn.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-9.0#define-supported-request-content-types-with-the-consumes-attribute-1:

[ApiController]
[Route("api/[controller]")]
public class ConsumesController : ControllerBase
{
    [HttpPost]
    [Consumes("application/json")]
    public IActionResult PostJson(IEnumerable<int> values) =>
        Ok(new { Consumes = "application/json", Values = values });

    [HttpPost]
    [Consumes("application/x-www-form-urlencoded")]
    public IActionResult PostForm([FromForm] IEnumerable<int> values) =>
        Ok(new { Consumes = "application/x-www-form-urlencoded", Values = values });
}

Observe that the JSON body is excluded from the OpenAPI document produced by Microsoft.AspNetCore.OpenApi. Only the form data body is present:

    "/api/Consumes": {
      "post": {
        "tags": [
          "Consumes"
        ],
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "values": {
                    "type": "array",
                    "items": {
                      "type": "integer",
                      "format": "int32"
                    }
                  }
                }
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },

Exceptions (if any)

No response

.NET Version

9.0.100-rc.2.24474.11

Anything else?

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added the old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels label Oct 9, 2024
@martincostello martincostello added area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi and removed old-area-web-frameworks-do-not-use *DEPRECATED* This label is deprecated in favor of the area-mvc and area-minimal labels labels Oct 9, 2024
@ascott18
Copy link
Contributor Author

ascott18 commented Nov 14, 2024

As I looked into this more while developing a workaround, I'm realizing that the real crux of the issue is that this line:

operations[description.GetOperationType()] = operation;

is overwriting operations that have the same HTTP verb and path but differ by content type. It should be merging the operations when there's an existing item in operations that only differs by having different request body content types.

ascott18 added a commit to ascott18/AspNetCore that referenced this issue Apr 8, 2025
@ascott18 ascott18 linked a pull request Apr 8, 2025 that will close this issue
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-mvc Includes: MVC, Actions and Controllers, Localization, CORS, most templates feature-openapi
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants