How do I get a Dictionary<string, string>
from form-data
?
View model:
public class SubmitRequestModel
{
public Dictionary<string, string> InputFields { get; set; }
public List<IFormFile> Attachments { get; set; }
}
Action:
[HttpPut("{id:int}")]
public async Task<IActionResult> Submit(int id, [FromForm] SubmitRequestModel model)
{
// model.InputFields is initialized but its count is 0
// do whatever
}
This is an API controller. Not cshtml or razor related.
So the model.InputFields
is not null
but it's count is 0
. When I look at the raw request. I can see that the input is received, but it is not bound to the dictionary in the model.
The values of the Request.Form
collection: https://prnt.sc/11x532p
I need to use form data because we are uploading files with the request. This requires multipart/form-data
.
How do I successfully parse the data to the model?
Info on how I tested this:
I have swagger set-up. I import the generated Swagger OpenAPI json in to Postman and test this way. I believe that this should be the correct request, that Swagger generated. But I'm not sure if it formatted the dictionary the right way. It would be the right way for a JSON data request. But I'm not sure if that applicates here.
You can achieve this with custom IModelBinder
:
public class DictionaryBinder<TKey, TValue> : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
if (bindingContext.HttpContext.Request.HasFormContentType)
{
var form = bindingContext.HttpContext.Request.Form;
var data = JsonSerializer.Deserialize<Dictionary<TKey, TValue>>(form[bindingContext.FieldName]);
bindingContext.Result = ModelBindingResult.Success(data);
}
return Task.CompletedTask;
}
}
The model class will become:
public class SubmitRequestModel
{
[FromForm]
[ModelBinder(BinderType = typeof(DictionaryBinder<string, string>))]
public Dictionary<string, string> InputFields { get; set; }
public List<IFormFile> Attachments { get; set; }
}