Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable documentation and file upload for formData parameter in Swashbuckle 5.6.3 for OpenApi 3?

We just ported a web API project to ASP.NET Core 5.0 and recent Swashbuckle. Currently the form file parameter does not show in the generated API documentation and we're also missing the ability to upload the file in Swagger UI.

We have a simple file upload method which gets a name as parameter and the file content from the form:

[HttpPut("{fileName:maxlength(255)}", Name = OpIdTemplate]
[HttpPost("{fileName:maxlength(255)}", Name = OpIdTemplate]
[ProducesResponseType(StatusCodes.Status201Created)]
public IActionResult CreateOrUpdate(string fileName)
{
    // checks omitted to provide a minimal example
    file = Request.Form.Files.Single();
    var sanitizedName = _fileHandler.Store(fileName, file);
    return CreatedAtRout(Urn, new { fileName = sanitizedFileName }, null);
}

Currently the required form file does not get documented in the generated openapi definition. How can we get swashbuckle to include that required form file?

We already tried using an IFormFile parameter

public IActionResult CreateOrUpdate(
    [FromRoute] string fileName,
    [FromBody] List<IFormFile> file)
{
    // ...
}

but that breaks existing clients (they get a 415 unsupported media type).

Previously you could extend swashbuckle with a custom IOperationFilter adding a Parameter with In = "formData".

Unfortunately you can no longer do this as OpenApiParameter.In is a ParameterLocation that only has Query, Header, Path and Cookie as possible values.

public class FileCreateOrUpdateFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var isCreateOrUpdate = true;// for simplicity
        if (isCreateOrUpdate)
        {
            operation.Parameters.Add(new OpenApiParameter
            {
                Name = "fileContent",
                In = new ParameterLocation("formData"),// invalid
            });
        }
    }
}

EDIT: If I write the YAML myself and feed it to the Swagger Editor, it shows the file upload button as expected. So the problem is to get Swashbuckle to generate the content multipart/form-data: section somehow.

    post:
      description: upload an audio file
      - in: path
        name: fileName
        schema:
          type: string
        required: true
        description: intended name of the file
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                # 'file' will be the field name in this multipart request
                file:
                  type: string
                  format: binary
      responses:
        201:
          description: return location of created resource (file name may vary from intended name)

So is there a way to add API documentation of the file parameter when using it from Request.Form.Files in Swashbuckle 5.6.3 or later? What has to be done to enable the file upload in Swagger UI then?

like image 822
mbx Avatar asked Sep 01 '25 04:09

mbx


1 Answers

We can actually do that with an IOperationFilter by setting the RequestBody explicitly:

public class FileCreateOrUpdateFilter : IOperationFilter
{
    public void Apply(OpenApiOperation operation, OperationFilterContext context)
    {
        var isCreateOrUpdate = true;// for simplicity, in RL you'd check on some context.MethodInfo properties to match the desired operation)
        if (isCreateOrUpdate)
        {
            operation.RequestBody = new OpenApiRequestBody
            {
                Description = "file to upload",
                Content = new Dictionary<String, OpenApiMediaType>
                {
                    {
                        "multipart/form-data", new OpenApiMediaType
                        {
                            Schema = new OpenApiSchema
                            {
                                Type = "object",
                                Required = new HashSet<String>{ "file" },
                                Properties = new Dictionary<String, OpenApiSchema>
                                {
                                    {
                                        "file", new OpenApiSchema()
                                        {
                                            // matches our handcrafted yaml
                                            Type = "string",
                                            Format = "binary"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            };
        }
    }
}

Now that we have the filter, we need to enable it in Startup.cs:

services.AddSwaggerGen(c =>
{
    
    // ...

    c.OperationFilter<FileCreateOrUpdateFilter>();
}

This should generate the expected json/yaml output. Once that is generated, Swagger UI (and Swagger Editor) will show the file upload button and you can test the file upload right there.

like image 71
mbx Avatar answered Sep 03 '25 00:09

mbx