Home > Software design >  ASP NET CORE 5 - Pass master-detail object (with file) to controller
ASP NET CORE 5 - Pass master-detail object (with file) to controller

Time:01-19

I have an model with this structure:

public class MasterDTO 
{
    [Required(ErrorMessage = Constants.Message.DefaultTextFieldRequired)]
    [MaxLength(250, ErrorMessage = Constants.Message.MaxLength)]
    public string Comments { get; set; }

    [Required(ErrorMessage = Constants.Message.DefaultTextFieldRequired)]
    [AllowedExtensions(new[] { ".jpg", ".png", ".jpg", ".doc", ".docx", ".pdf" })]
    public IFormFile File { get; set; }

    public List<DetailDTO> Details { get; set; }

    public MasterDTO()
    {
        this.Details = new List<DetailDTO>();
    }
}


public class DetailDTO 
{              
    public Int64 ElementId { get; set; }

    public double LowerLimit { get; set; }

    public double HigherLimit { get; set; }

    [ValidValues(new[] {"A", "O", "R" })]
    public string Status { get; set; }

    [MaxLength(150, ErrorMessage = Constants.Message.MaxLength)]
    public string UserAuthorization { get; set; }

    public DateTime? AutorizationDate { get; set; }
}

In the controller:

public async Task<IActionResult> CreateProjectLimit([FromForm] MasterDto masterDto)
{
    ...

    return Ok();
}

The html form is configured like multipart/form-data

I'm testing with swagger.

My problem is about Details property. I can get the comments and the file, but Details always is empty (empty, not null).

My approach is wrong about IFromFile? What's my mistake?

Thanks!

CodePudding user response:

It is a enter image description here

Then custom model binder like below:

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;
    }
}

Add the model binder to the model class:

public class MasterDTO
{
    public string Comments { get; set; }
    public IFormFile File { get; set; }        
    public List<DetailDTO> Details { get; set; }

    public MasterDTO()
    {
        this.Details = new List<DetailDTO>();
    }
}

[ModelBinder(BinderType = typeof(MetadataValueModelBinder))]
public class DetailDTO
{
    public Int64 ElementId { get; set; }

    public double LowerLimit { get; set; }

    public double HigherLimit { get; set; }

    public string Status { get; set; }

    public string UserAuthorization { get; set; }

    public DateTime? AutorizationDate { get; set; }
}
  •  Tags:  
  • Related