I have a controller method to accept multipart/form-data request with primitive types, File and List of objects. I saw that I need custom model binder when I have complex data type using FromForm and I made one, but the problem is that binding works from Swagger, but not from Postman.
Here is my controller method first:
public async Task<IActionResult> Post([FromForm] AddRequest addRequest)
{
var result = await _service.AddAsync(addRequest);
if (result.Success)
{
return Ok(result);
}
return BadRequest();
}
My request looks like this:
public class AddRequest
{
public string? Name { get; set; }
public string? Description { get; set;}
public IFormFile? File { get; set; }
public IEnumerable<LocaleViewModel>? Locales { get; set; }
}
And here is my viewmodel:
[ModelBinder(BinderType = typeof(MetadataValueModelBinder))]
public class LocaleViewModel
{
public long Id { get; set; }
public string Code { get; set; }
}
And finally model binder:
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;
}
}
So, when I fire request from Swagger, binding is done correctly and model name is Locales, but when I do it from Postman or my SPA, binding is not working and model name is Locales[0]. Am I missing something in my model binder or I'm doing everything completely wrong?
I was trying to understand how ValueProvider.GetValue works but with no success.
CodePudding user response:
How do you pass parameters in postman? Please try like this: