domaindrivendev / Swashbuckle.AspNetCore

Swagger tools for documenting API's built on ASP.NET Core
MIT License
5.26k stars 1.32k forks source link

[Bug]: Incorrect swagger.json generation in Minimal API when using FromForm parameters without the WithOpenApi extension method #3126

Closed marcominerva closed 1 week ago

marcominerva commented 2 weeks ago

Describe the bug

I have the following endpoints:

app.MapPost("/api/products", ([FromForm] Product product) =>
{
    return TypedResults.NoContent();
})
.DisableAntiforgery();

app.MapPost("/api/products-with-openapi", ([FromForm] Product product) =>
{
    return TypedResults.NoContent();
})
.DisableAntiforgery()
.WithOpenApi();

public record class Product(string Name, double Price);

These endpoints differ only for the WithOpenApi extension method, but the swagger.json definition is quite different:

"/api/products": {
  "post": {
    "tags": [
      "FromFormIssue"
    ],
    "requestBody": {
      "content": {
        "multipart/form-data": {
          "schema": {
            "required": [
              "product"
            ],
            "type": "object",
            "properties": {
              "product": {
                "$ref": "#/components/schemas/Product"
              }
            }
          },
          "encoding": {
            "product": {
              "style": "form"
            }
          }
        },
        "application/x-www-form-urlencoded": {
          "schema": {
            "required": [
              "product"
            ],
            "type": "object",
            "properties": {
              "product": {
                "$ref": "#/components/schemas/Product"
              }
            }
          },
          "encoding": {
            "product": {
              "style": "form"
            }
          }
        }
      }
    },
    "responses": {
      "204": {
        "description": "No Content"
      }
    }
  }
}

"/api/products-with-openapi": {
  "post": {
    "tags": [
      "FromFormIssue"
    ],
    "requestBody": {
      "content": {
        "multipart/form-data": {
          "schema": {
            "$ref": "#/components/schemas/Product"
          }
        },
        "application/x-www-form-urlencoded": {
          "schema": {
            "$ref": "#/components/schemas/Product"
          }
        }
      },
      "required": true
    },
    "responses": {
      "204": {
        "description": "No Content"
      }
    }
  }
}

So, in Swagger I get the following result:

WRONG image

CORRECT image

Expected behavior

Both the endpoints should produce the same swagger.json definition that defines the parameters from Form.

Actual behavior

No response

Steps to reproduce

Minimal repro here: https://github.com/marcominerva/FromFormIssue

Exception(s) (if any)

No response

Swashbuckle.AspNetCore version

6.9.0

.NET Version

8.0.403

Anything else?

No response

jgarciadelanoceda commented 2 weeks ago

I am going to take a look at these ( the controllers reports every Property of an object in the description, but MinimalApi seems to just report the type)

jgarciadelanoceda commented 2 weeks ago

Almost there! I am thinking about make the OpenApi almost equal for WithOpenApi/MinimalApi/Controllers.

The only difference that exists right now is that controllers put each property of the object in the ApiDescription and Minimal doesn't.

There is a small issue when there are 2 or more properties ( for example strings in a Form).. The WithOpenApi extension method puts AllOf whereas MinimalApi just writes two properties ( Both options are correct).

Given the errors we had in previous versions it seems reasonable to do this breaking change(For WithOpenApi extensions)

To make things clearer I am going to create a PR with just the fix, and apply later in the same PR the Breaking change