当输入参数之一是文件时,Swashbuckle UI 问题
Swashbuckle UI problem when one of the input parameter is a file
我正在尝试上传包含一些元数据的文件:
Upload(IFormFile file, [FromForm]IEnumerable<MetadataValue> list)
public class MetadataValue
{
public Metadata Metadata { get; set; }
public string Value { get; set; }
}
public enum Metadata
{
Cat1,
Cat2
}
MetadataValue
列表显示为字符串输入数组。我无法确定我应该如何将数据传递给控制器 - 我总是收到一个空集合。
当我从 Postman 发送请求时一切正常。这是由点 pattern/notation.
处理的
在 Postman 中,复杂对象的每个参数和每个 属性 都作为单独的字段发送:
curl --location --request POST 'https://localhost:44395/api/document/upload' \
--form 'file=@/C:/FilterDraft.txt' \
--form 'list[0].metadata=Cat1' \
--form 'list[0].value=ABC' \
--form 'list[1].metadata=Cat2' \
--form 'list[1].value=DEF'
如何在 Swagger 中实现此目的 UI?
如何配置 Swagger 以获得更好的 UI 生成?
我正在使用:
- .NET 核心 3.1
- Swashbuckle.AspNetCore 5.5.1
解决方案:
要添加示例,您必须使用 SwaggerOperationFilter 修饰操作方法:
[SwaggerOperationFilter(typeof(OperationFilter))]
Upload(IFormFile file, [FromForm]IEnumerable<MetadataValue> list)
[...]
internal class UploadOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.OperationId != nameof(DocumentController.Upload))
{
return;
}
if (operation.RequestBody.Content.TryGetValue("multipart/form-data", out var openApiMediaType))
{
var options = new JsonSerializerOptions { WriteIndented = true };
options.Converters.Add(new JsonStringEnumConverter());
var array = new OpenApiArray
{
new OpenApiString(JsonSerializer.Serialize(new MetadataValue {Metadata = Metadata.Cat1, Value = "ABC"}, options)),
new OpenApiString(JsonSerializer.Serialize(new MetadataValue {Metadata = Metadata.Cat2, Value = "DEF"}, options))
};
openApiMediaType.Schema.Properties["metadata"].Example = array;
}
}
}
要在控制器中获取值(不是空集合),您必须添加自定义 ModelBinder:
[ModelBinder(BinderType = typeof(MetadataValueModelBinder))]
public class MetadataValue
{
public Metadata Metadata { get; set; }
public string Value { get; set; }
}
public class MetadataValueModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (values.Length == 0)
return Task.CompletedTask;
var options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter());
var deserialized = JsonSerializer.Deserialize(values.FirstValue, bindingContext.ModelType, options);
bindingContext.Result = ModelBindingResult.Success(deserialized);
return Task.CompletedTask;
}
}
我正在尝试上传包含一些元数据的文件:
Upload(IFormFile file, [FromForm]IEnumerable<MetadataValue> list)
public class MetadataValue
{
public Metadata Metadata { get; set; }
public string Value { get; set; }
}
public enum Metadata
{
Cat1,
Cat2
}
MetadataValue
列表显示为字符串输入数组。我无法确定我应该如何将数据传递给控制器 - 我总是收到一个空集合。
当我从 Postman 发送请求时一切正常。这是由点 pattern/notation.
处理的在 Postman 中,复杂对象的每个参数和每个 属性 都作为单独的字段发送:
curl --location --request POST 'https://localhost:44395/api/document/upload' \
--form 'file=@/C:/FilterDraft.txt' \
--form 'list[0].metadata=Cat1' \
--form 'list[0].value=ABC' \
--form 'list[1].metadata=Cat2' \
--form 'list[1].value=DEF'
如何在 Swagger 中实现此目的 UI?
如何配置 Swagger 以获得更好的 UI 生成?
我正在使用:
- .NET 核心 3.1
- Swashbuckle.AspNetCore 5.5.1
解决方案:
要添加示例,您必须使用 SwaggerOperationFilter 修饰操作方法:
[SwaggerOperationFilter(typeof(OperationFilter))]
Upload(IFormFile file, [FromForm]IEnumerable<MetadataValue> list)
[...]
internal class UploadOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.OperationId != nameof(DocumentController.Upload))
{
return;
}
if (operation.RequestBody.Content.TryGetValue("multipart/form-data", out var openApiMediaType))
{
var options = new JsonSerializerOptions { WriteIndented = true };
options.Converters.Add(new JsonStringEnumConverter());
var array = new OpenApiArray
{
new OpenApiString(JsonSerializer.Serialize(new MetadataValue {Metadata = Metadata.Cat1, Value = "ABC"}, options)),
new OpenApiString(JsonSerializer.Serialize(new MetadataValue {Metadata = Metadata.Cat2, Value = "DEF"}, options))
};
openApiMediaType.Schema.Properties["metadata"].Example = array;
}
}
}
要在控制器中获取值(不是空集合),您必须添加自定义 ModelBinder:
[ModelBinder(BinderType = typeof(MetadataValueModelBinder))]
public class MetadataValue
{
public Metadata Metadata { get; set; }
public string Value { get; set; }
}
public class MetadataValueModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
var values = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (values.Length == 0)
return Task.CompletedTask;
var options = new JsonSerializerOptions();
options.Converters.Add(new JsonStringEnumConverter());
var deserialized = JsonSerializer.Deserialize(values.FirstValue, bindingContext.ModelType, options);
bindingContext.Result = ModelBindingResult.Success(deserialized);
return Task.CompletedTask;
}
}