2

I have a simple model:

public class MyModel {
   public string Description { get; set; }
   public HttpPostedFileBase File {get; set; }
}

and my MVC action:

[HttpPost]
public ActionResult Upload(List<MyModel> data) {
   // do soemthing
}

and finally JavaScript:

$("#chooseFile").on("change", function (){
    var files = $(this).prop("files");
    var array = [];    

   for(int i=0; i<files.length; i++) {
      var obj = {};
      obj.Description = "My custom description" + i;
      obj.File = files[i];

      array.push(obj);
   }

   var formData = new FormData();
   formData.append("data", array);

   var xmlHttpRequest = new XMLHttpRequest();
   xmlHttpRequest.open("POST", "/test/Upload");
   xmlHttpRequest.send(formData);
});

The problem is that data from the Upload action always has Count = 0 . Where is my mistake ?

mcserep
  • 3,231
  • 21
  • 36
Snake Eyes
  • 16,287
  • 34
  • 113
  • 221
  • possible duplicate of [how to append whole set of model to formdata and obtain it in MVC](http://stackoverflow.com/questions/29293637/how-to-append-whole-set-of-model-to-formdata-and-obtain-it-in-mvc) –  May 22 '15 at 11:18
  • @StephenMuecke: That won't help me... Please read question, not title. – Snake Eyes May 22 '15 at 11:19
  • Because I send a custom list of object, this has nothing to do with form except choosing file from local computer. – Snake Eyes May 22 '15 at 11:21
  • Then just a matter or correctly naming what you post back (with indexers) so that it binds to your model. –  May 22 '15 at 11:23
  • IT works only if I add `formData.append(data, "files[i]")` and in action I put `List data`, works perfectly. I don't know why is not working with custom objects ... – Snake Eyes May 22 '15 at 11:33
  • Have not tested, but `formData.append('[0].Description', 'abc'); formData.append('[0].File', files[0]); formData.append('[1].Description', 'def'); formData.append('[1].File', files[1]);` etc should work –  May 22 '15 at 11:39
  • Oh, my God, thanks a million. Please post your last command as answer, and I'll accept it !!! – Snake Eyes May 22 '15 at 11:47

1 Answers1

2

In order bind to a collection of complex objects, the names (in the name/value pairs) must include indexers. Your script needs to add the names to FormData in the following format - '[0].Files', '[0].Description', '[1].Files', '[1].Description' etc

$("#chooseFile").on("change", function() {
  var files = $(this).prop("files");
  var formData = new FormData();
  for(int i=0; i<files.length; i++) {
    formData.append('[' + i + '].File', files[i]);
    formData.append('[' + i + '].Description', 'My custom description' + i);
  }
  var xmlHttpRequest = new XMLHttpRequest();
  ....
  • How would you append if there are multiple lists `List1, List2`, how would you identify a particular list. How about `formData.append('List1[' + i + '].File', files[i]);`? – Bilal Ahmed Mar 21 '17 at 14:12
  • 1
    @BilalAhmed, If you model contains a collection property named `List` where each object in the collection contains a property named `File`, then that is exactly how you would do it. –  Mar 21 '17 at 22:33