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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With