I got problem similar to this one Link, but I can't find a solution. Swagger has problems uploading the list of objects. The API reads the list of passed InterestDto's as empty. The problem only occurs in swagger, a properly constructed query in Postman works. This particular snippet deals with request with multipart/form-data, but the same problem occurs elsewhere when using query. Here's my attempt at dealing with it, which unfortunately doesn't work. It gives an error:
System.Collections.Generic.KeyNotFoundException
HResult=0x80131577
Message=The given key 'Interests' was not present in the dictionary.
Source=System.Private.CoreLib
StackTrace:
at System.ThrowHelper.ThrowKeyNotFoundException[T](T key)
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Flats4us.Helpers.CustomOperationFilter.Apply(OpenApiOperation operation, OperationFilterContext context) in C:\Dane\Projekty\Flats4Us\Flats4us\Flats4us\Helpers\CustomOperationFilter.cs:line 23
at Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperation(ApiDescription apiDescription, SchemaRepository schemaRepository)
AuthController.cs:
[HttpPost("register/Student")]
public async Task<ActionResult<User>> RegisterStudentAsync([FromForm] StudentRegisterDto request)
{
try
{
await _userService.RegisterStudentAsync(request);
return Ok("Registered successfully");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
UserRegisterDto.cs:
[ModelBinder(BinderType = typeof(MetadataValueModelBinder))]
public class StudentRegisterDto : OwnerStudentRegisterDto
{
[...]
public List<InterestDto> Interests { get; set; }
}
Program.cs:
builder.Services.AddSwaggerGen(options =>
{
options.OperationFilter<CustomOperationFilter>();
[...]
}
MetadataValueModelBinder.cs:
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() { PropertyNameCaseInsensitive = true };
var deserialized = JsonSerializer.Deserialize(values.FirstValue, bindingContext.ModelType, options);
bindingContext.Result = ModelBindingResult.Success(deserialized);
return Task.CompletedTask;
}
}
CustomOperationFilter.cs:
public class CustomOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.RequestBody != null && operation.RequestBody.Content.TryGetValue("multipart/form-data", out var openApiMediaType))
{
var options = new JsonSerializerOptions { WriteIndented = true };
var array = new OpenApiArray
{
new OpenApiString(JsonSerializer.Serialize(new InterestDto {InterestId = 0, Name="string"}, options)),
};
openApiMediaType.Schema.Properties["Interests"].Example = array;
};
}
}
/// <example>Hello world</example>by hand?