0

Previously, I just had a requirement to create a form that contains only data to be sent to the action and not the image, now, I've confronted with a requirement to POST the data along with an image to the action. I've no idea how to append the image to the data so that I can get it work to proceed further in action.

This is how I'm posting the data and the image together but I receive null in action :

HTML

<input type="file" id="profilePic" name="file" value="Browse">
<input type="text" id="EmployeeCode" name="EmployeeCode" value="EmployeeCode">
<input type="text" id="SystemCode" name="SystemCode" value="SystemCode">
<input type="button" value="Create" onclick="SaveEmpData()" />

I know how to get the input type text data and send it through ajax request and in a json format and save it to database, but when it comes to get the data and image through the ajax request in a json format, I've got no clue about how to do this.

JS

var empdata = { "SystemCode": "", "EmployeeCode": "" };

empdata.EmployeeCode = $("#EmployeeCode").val();
empdata.SystemCode = $("#SystemCode").val();

var data = new FormData();
var files = $("#profilePic").get(0).files;    
data.append("Image", files[0]); 

Ajax

$.ajax({
    url: '/EmployeeMasterA/Create',
    headers: headers,
    data: JSON.stringify({ employeeMasterA: empdata, profilePic: data }),
    type: 'POST',
    dataType: 'json',
    contentType: 'application/json',
    traditional: true,
    success: function (result) {

        if (result.Success == "1") {
            window.location.href = "/EmployeeMasterA/Index";
        }
        else {
            alert(result.ex);
        }
    }
});

and Create Action :

[HttpPost]
public ActionResult Create([Bind(Include = "SystemCode,EmployeeCode")] EmployeeMasterA employeeMasterA, HttpPostedFileBase profilePic)
{            
    var pic = System.Web.HttpContext.Current.Request.Files["Image"];
}

In the above code, the pic variable is null. My question is:

What is the proper way to get the data + image from the form, and send it through the ajax request to the action? Any help is deeply appreciated :)

Update

After referring to liran's answer, I tried binding by editing my code this way :

JS

var empbind = { "profilePic" : "", "employeeMasterA" : "" };
// Created empdata and data (image) object as mentioned above
empbind.employeeMasterA = empdata;
empbind.profilePic = data;
var empbindjson = JSON.stringify(empbind);

and changed the Ajax data parameter as below :

$.ajax({
   .
   .
   data: empbindjson,
   .
   .
});

And Changed my controller action :

[HttpPost]
public ActionResult Create([Bind(Include = "employeeMasterA,profilePic")]       EmployeeBind bind)
{            
    var pic = System.Web.HttpContext.Current.Request.Files["Image"];
}

Both employeeMasterA,profilePic are received null in debug mode of the above code, this is my new class for binding :

public class EmployeeBind
{
    public EmployeeMasterA employeeMasterA { get; set; }
    public HttpPostedFileBase profilePic { get; set; }
}

Ok, Now, I've changed my code to bind it with the profilePic, Is there any thing I doing wrong? because both bind parameter of the create action contains null for both employeeMasterA and profilePic.

Bilal Ahmed
  • 1,043
  • 4
  • 17
  • 32

1 Answers1

0

Try change something like that need to work:

  $('#save').click(function () {

    var form = $("#yourForm");
    var data = new FormData();
    var files = $("#profilePic").get(0).files;
    data.append("Image", files[0]);
    $.each(form.serializeArray(), function (key, input) {
        data.append(input.name, input.value);
    });

  $.ajax({
      url: '/EmployeeMasterA/Create',
      data: data,
      type: 'POST',
      processData: false,
      contentType: false,
      success: function (result) {

          if (result.Success == "1") {
              window.location.href = "/EmployeeMasterA/Index";
          }
          else {
              alert(result.ex);
          }
      }
  });
});

In Html:

 <form id="yourForm">
    <input type="file" id="profilePic" name="file" value="Browse">
    <input type="text" id="EmployeeCode" name="EmployeeCode" value="EmployeeCode">
    <input type="text" id="SystemCode" name="SystemCode" value="SystemCode">
    <input type="button" value="Create" onclick="SaveEmpData()" id="save">
</form>

Edit: if that still not working so bind the EmployeeMasterA and HttpPostedFileBase to same class something like :

    [HttpPost]
    public ActionResult Create([Bind(Include = "SystemCode,EmployeeCode")] VMNewClass bind)
    {            
        var pic = System.Web.HttpContext.Current.Request.Files["Image"];
    }


public class VMNewClass{

 public EmployeeMasterA employeeMasterA {get;set;}
 public  HttpPostedFileBase profilePic {get;set;}

}

response

if you don't want to do:

 $.each(form.serializeArray(), function (key, input) {
        data.append(input.name, input.value);
    });

you can write:

var data = new FormData();
    var files = $("#profilePic").get(0).files;
    data.append("profilePic", files[0]);
    data.append("EmployeeCode", $("#EmployeeCode").val());
    data.append("SystemCode", $("#SystemCode").val());

Edit if article I've attached in comment

 <script>
        var empdata = { "SystemCode": "", "EmployeeCode": "" };

        empdata.EmployeeCode = $("#EmployeeCode").val();
        empdata.SystemCode = $("#SystemCode").val();

        var data = new FormData();
        var files = $("#profilePic").get(0).files;
        data.append("Image", files[0]);
        data.append("EmployeeCode", $("#EmployeeCode").val());
        data.append("SystemCode", $("#SystemCode").val());

        $.ajax({
            url: '/EmployeeMasterA/Create',
            data: data,
            type: 'POST',
            contentType: false, // Not to set any content header  
            processData: false, // Not to process data  
            success: function (result) {

                if (result.Success == "1") {
                }
                else {
                    alert(result.ex);
                }
            }
        });

</script>

Controller :

[HttpPost]
public ActionResult Create([Bind(Include = "SystemCode,EmployeeCode")] EmployeeMasterA employeeMasterA)
{            
    HttpPostedFileBase profilePic = Request.Files[0]; // your file
}
Liran
  • 323
  • 2
  • 16
  • I don't want to do form.serialize() because I've a huge form with huge data in one to many relationship, so,to keep the question simple,I just added two textbox fields `EmployeeCode, SystemCode` instead of all 260 fields. Now, I somehow managed to create the json object of all these 260 fields i.e. `empdata`,I can't change this `empdata` object because, If only `empdata` is concerned, it works fine, I just want to add one more thing in `empdata` i.e. the `profilePic`,how should I append `profilePic` with `empdata` or is there any different way to pass `profilePic` without disturbing `empdata`? – Bilal Ahmed Mar 20 '17 at 14:39
  • Please, do refer to my updated question. – Bilal Ahmed Mar 20 '17 at 15:59
  • Yes, I understand so myabe use Request.Files [File Upload](http://www.c-sharpcorner.com/UploadFile/manas1/upload-files-through-jquery-ajax-in-Asp-Net-mvc/) I edit my answer with article I've attached for you if still not help you I hope someone else can help good day :) – Liran Mar 20 '17 at 16:02
  • In the first answer I add to ajax processData: false, contentType: false I checked my code and it's working (also the second answer works to me) – Liran Mar 20 '17 at 17:18