I ended up resorting to a code not very familiar(I was just sent a link with a code ready).
Explaining:
Create a custom model:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace TestMultipart.ModelBinding
{
public class JsonWithFilesFormDataModelBinder : IModelBinder
{
private readonly IOptions<MvcJsonOptions> _jsonOptions;
private readonly FormFileModelBinder _formFileModelBinder;
public JsonWithFilesFormDataModelBinder(IOptions<MvcJsonOptions> jsonOptions, ILoggerFactory loggerFactory)
{
_jsonOptions = jsonOptions;
_formFileModelBinder = new FormFileModelBinder(loggerFactory);
}
public async Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
// Retrieve the form part containing the JSON
var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);
if (valueResult == ValueProviderResult.None)
{
// The JSON was not found
var message = bindingContext.ModelMetadata.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(bindingContext.FieldName);
bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, message);
return;
}
var rawValue = valueResult.FirstValue;
// Deserialize the JSON
var model = JsonConvert.DeserializeObject(rawValue, bindingContext.ModelType, _jsonOptions.Value.SerializerSettings);
// Now, bind each of the IFormFile properties from the other form parts
foreach (var property in bindingContext.ModelMetadata.Properties)
{
if (property.ModelType != typeof(IFormFile))
continue;
var fieldName = property.BinderModelName ?? property.PropertyName;
var modelName = fieldName;
var propertyModel = property.PropertyGetter(bindingContext.Model);
ModelBindingResult propertyResult;
using (bindingContext.EnterNestedScope(property, fieldName, modelName, propertyModel))
{
await _formFileModelBinder.BindModelAsync(bindingContext);
propertyResult = bindingContext.Result;
}
if (propertyResult.IsModelSet)
{
// The IFormFile was sucessfully bound, assign it to the corresponding property of the model
property.PropertySetter(model, propertyResult.Model);
}
else if (property.IsBindingRequired)
{
var message = property.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(fieldName);
bindingContext.ModelState.TryAddModelError(modelName, message);
}
}
// Set the successfully constructed model as the result of the model binding
bindingContext.Result = ModelBindingResult.Success(model);
}
}
}
Add as a Dataannotationion
Banners.DTO
using Microsoft.AspNetCore.Mvc;
namespace LR.Manager.Banner.Entidades
{
[ModelBinder(typeof(JsonWithFilesFormDataModelBinder), Name = "json")]
public class BannersDTO
{
public Microsoft.AspNetCore.Http.IFormFile Files { get; set; }
public string TermoOrSku { get; set; }
public bool InserirImediato { get; set; }
public string DataAtivacao { get; set; }
public string DataVigencia { get; set; }
}
}
On the controller:
[HttpPost]
public async Task<ActionResult> Post(BannersDTO banners)
{
Modify the request:
submit () {
let data = {}
const { termoOrSku, inserirImediato, dataAtivacao, dataVigencia } = this.banners
data.termoOrSku = termoOrSku
data.inserirImediato = inserirImediato
data.dataAtivacao = dataAtivacao
data.dataVigencia = dataVigencia
const files = new FormData()
files.append('files', this.banners.files)
files.append('json', JSON.stringify(data))
this.$axios.post(api.insertBanner, files).then(response => response.data)
.catch(error => {
console.log(error)
})
},
See that I had to create a form-data with the File and another with JSON. For the little I understood of the customized model the json is deserialized and a map property is made property by property.