mattfrear / Swashbuckle.AspNetCore.Filters

A bunch of useful filters for Swashbuckle.AspNetCore
MIT License
430 stars 80 forks source link

Not possible to create request examples for multipart/form-data Content-Type #248

Closed efqz11 closed 4 months ago

efqz11 commented 5 months ago

Isn't it possible to create request examples for API endpoint with [FromForm] attribute?

What I would like to create a request example for a controller method with the following signature:

[HttpPost]
[Route("upload")]
// [Consumes("multipart/form-data")]
[SwaggerRequestExample(typeof(FileUploadModel), typeof(FileUploadModelExample))]
public IActionResult UploadFile([FromForm] FileUploadModel model)
{
    // Handle file upload
    return Ok();
}

Request Modal:

public class FileUploadModel
{
    public IFormFile File { get; set; }
    public string Description { get; set; }
}

Example Provider

public class FileUploadModelExample : IExamplesProvider<FileUploadModel>
{
    public FileUploadModel GetExamples()
    {
        return new FileUploadModel
        {
            Description = "Sample description"
            // The File property can't be demonstrated directly as it's a binary type.
        };
    }
}

In program.cs

    builder.Services.AddControllers();

    builder.Services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });

        // c.OperationFilter<MultipartFormDataOperationFilter>(); for further testing
        c.ExampleFilters();

    });

    builder.Services.AddSwaggerExamplesFromAssemblyOf<FileUploadModelExample>();

With these configurations, in UI parameters are still empty.

In swagger.json file, it is observed example definition here

"content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "properties": {
                  "File": {
                    "type": "string",
                    "format": "binary"
                  },
                  "Description": {
                    "type": "string"
                  }
                }
              },
              "example": {"file":null,"description":"Sample description"},
              "encoding": {
                "File": {
                  "style": "form"
                },
                "Description": {
                  "style": "form"
                }
              }
            }
          }

Also tried with operationFilter

public class MultipartFormDataOperationFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var consumesAttributes = context.MethodInfo
            .GetCustomAttributes(typeof(ConsumesAttribute), false)
            .Cast<ConsumesAttribute>();

        if (consumesAttributes.Any(c => c.ContentTypes.Contains("multipart/form-data")))
        {
            var requestBody = operation.RequestBody;
            if (requestBody != null)
            {
                var content = requestBody.Content["multipart/form-data"];
                content.Example = new OpenApiObject
                {
                    ["file"] = new OpenApiString("example.jpg"),
                    ["description"] = new OpenApiString("Sample description")
                };
            }
        }
    }
}

Unfortunately the same, without generating request examples

Thanks a lot in advance!

mattfrear commented 4 months ago

If the example is in the swagger.json, then it's not a bug with this library. If it's not being displayed, then that is a bug with Swagger-UI.

I did a quick search and I can see someone else was having the same problem over here: https://github.com/swagger-api/swagger-ui/issues/8494

Closing this issue, is it sounds like it's a bug with Swagger-UI.