0

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;
        };
    }
}
2
  • Are you trying to implement /// <example>Hello world</example> by hand? Commented Dec 4, 2023 at 0:41
  • Hi @giziuuu, what is your OwnerStudentRegisterDto like? Did you debug your code step by step to check which line makes such error? Does it make error in CustomOperationFilter? Could you pls also share your target framework and swagger version? Commented Dec 4, 2023 at 5:56

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.