Add support for multipart/data uploads in swagger
This commit is contained in:
@@ -5,6 +5,7 @@ using FrameProcessor.Middleware;
|
||||
using FrameProcessor.Mqtt;
|
||||
using FrameProcessor.Storage;
|
||||
using FrameProcessor.UrlFetch;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.OpenApi;
|
||||
using Serilog;
|
||||
@@ -50,6 +51,68 @@ builder.Services.AddOpenApi(options =>
|
||||
];
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
|
||||
// Microsoft.AspNetCore.OpenApi (10.0) does not emit a multipart/form-data
|
||||
// request body for [FromForm] IFormFile parameters on MVC controllers, so
|
||||
// Swagger UI renders no upload widget. Synthesize one here for any operation
|
||||
// whose action takes form-bound parameters.
|
||||
options.AddOperationTransformer((operation, context, _) =>
|
||||
{
|
||||
var formParams = context.Description.ParameterDescriptions
|
||||
.Where(p => p.Source == BindingSource.FormFile || p.Source == BindingSource.Form)
|
||||
.ToList();
|
||||
|
||||
if (formParams.Count == 0)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
var properties = new Dictionary<string, IOpenApiSchema>();
|
||||
var required = new HashSet<string>();
|
||||
|
||||
foreach (var p in formParams)
|
||||
{
|
||||
var isFile = p.Source == BindingSource.FormFile
|
||||
|| typeof(IFormFile).IsAssignableFrom(p.ModelMetadata?.ModelType);
|
||||
|
||||
properties[p.Name] = new OpenApiSchema
|
||||
{
|
||||
Type = JsonSchemaType.String,
|
||||
Format = isFile ? "binary" : null,
|
||||
};
|
||||
|
||||
if (p.IsRequired)
|
||||
{
|
||||
required.Add(p.Name);
|
||||
}
|
||||
}
|
||||
|
||||
operation.RequestBody = new OpenApiRequestBody
|
||||
{
|
||||
Required = true,
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
["multipart/form-data"] = new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Type = JsonSchemaType.Object,
|
||||
Properties = properties,
|
||||
Required = required,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
if (operation.Parameters is { Count: > 0 })
|
||||
{
|
||||
var formNames = formParams.Select(p => p.Name).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
var filtered = operation.Parameters.Where(p => p.Name is null || !formNames.Contains(p.Name)).ToList();
|
||||
operation.Parameters = filtered.Count > 0 ? filtered : null;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
});
|
||||
});
|
||||
|
||||
builder.Services.AddOptions<MqttOptions>()
|
||||
|
||||
Reference in New Issue
Block a user