3

I have this submit code,

$('#form').on('submit',function (e) {
    e.preventDefault();
    //var file = $("#productImg");
    var fileUpload = $("#productImg").get(0);
    var files = fileUpload.files;


    var form = $("#form");
    var formData = new FormData();
    formData.append("product", form.serialize());

    // Looping over all files and add it to FormData object  
    for (var i = 0; i < files.length; i++) {
        formData.append(files[i].name, files[i]);
    }
    //formData.append("file", file);

    $.ajax({
        type: 'POST',
        url: baseUrl + 'Controller/Action',
        data: formData,
        processData: false,
        contentType: false,
        success: function (data) {
        }
    });
});

This is my controller :

  public JsonResult AddProduct(ProductModel product) // data is binded in the model if I remove content type property
    {
        var isSuccess = false;

        if (product != null)
        {
            try
            {
                if (Request.Files.Count > 0) // works ok if I added the content type property
                {
                    var sadas = "sad";
                }

So what's happening here is I sending the serialized form data into mvc controller together with the uploaded file.

The problem here is , when i added this ajax property contentType: false,, I can successfully postback the files, but the binded model is null.

On the other hand, If i remove this property, the binded model works OK. But the problem is the file was not sent in the server.

How can I make this work? I want both the form and images to be sent in server side.

UPDATE This is working now, the only line I changed is this

formData.append("product", form.serialize());

TO

var other_data = $('#addProductForm').serializeArray(); $.each(other_data, function (key, input) { formData.append(input.name, input.value); });

Can someone explain what is happening? I got no clue

2
  • 1
    Assuming the fil inputs are also in your form tags, then all you need is var formData = new FormData($("#form").get(0)); - refer this answer Commented Aug 2, 2016 at 10:30
  • @StephenMuecke thanks! this can simplify my code Commented Aug 2, 2016 at 10:48

3 Answers 3

10

Unfortunately the jQuery serialize() method will not include input file elements. So your files are not going to be included in the serialized value.

What you can do is, creating a FormData object, append the files to that. You need to append the form field values as well to this same FormData object. You may simply loop through all the input field and add it.

When you add the files to form data, you need to give a name which will match with the parameter you will use in your HttpPost action method.

This should work.

var fileUpload = $("#productImg").get(0);
var files = fileUpload.files;

var formData = new FormData();

// Looping over all files and add it to FormData object  
for (var i = 0; i < files.length; i++) {
    console.log('(files[i].name:' + files[i].name);
    formData.append('productImg', files[i]);
}

// You can update the jquery selector to use a css class if you want
$("input[type='text'").each(function (x, y) {
    formData.append($(y).attr("name"), $(y).val());
});

$.ajax({
    type: 'POST',
    url:  'ReplaceHereYourUrltotheActionMethod',
    data: formData,
    processData: false,
    contentType: false,
    success: function (data) {
    }
});

and your action method, You can add another parameter of type IEnumerable<HttpPostedFileBase> with the name same as what we set to form data, which is productImg.

[HttpPost]
public virtual ActionResult Index(ProductModel model, 
                                               IEnumerable<HttpPostedFileBase> productImg)
{
  // to do :Look through productImg and do something  
}
Sign up to request clarification or add additional context in comments.

2 Comments

can you explain my updated question? your answer is correct btw
Could you explain to me the part of why 2 parameters in the Action method, while you are just sending one formdata in the post method?
0

For ASP.NET Core, you can do this by starting with your model:

public class FilesViewModel
{
    public Guid? ParentObjectId { get; set; } // if you wish to associate these files with some parent record
    public IEnumerable<IFormFile> Files { get; set; }
}

Your controller:

[HttpPost]
public JsonResult UploadFiles(FilesViewModel model)
{
    if (ModelState.IsValid)
    {
        // your code here
        // see https://learn.microsoft.com/en-us/aspnet/core/mvc/models/file-uploads
    }
}

Your view (or view component):

@model YourProject.ViewModels.EventFilesViewModel
<form method="post" enctype="multipart/form-data">
    <input type="hidden" asp-for="ParentObjectId" />
    <input type="file" asp-for="Files" multiple />
    <span asp-validation-for="Files" class="text-danger"></span>
    <input type="button" id="btnEventFilesUpload" value="Upload Selected Files" class="btn btn-default" />
</form>

And, finally, the javascript (as modified from Shyju's answer to pass the ParentObjectId):

$(function () {
    $("#btnEventFilesUpload").click(function (evt) {
        var fileUpload = $("#Files").get(0);
        var files = fileUpload.files;
        var data = new FormData();
        for (var i = 0; i < files.length; i++) {
            data.append('Files', files[i]);
        }
        // if you wish to associate these files with some parent record
        data.append('ParentObjectId', $('#ParentObjectId').val());
        $.ajax({
            type: "POST",
            url: "/Event/UploadFiles",
            contentType: false,
            processData: false,
            data: data,
            success: function (message) {
                alert(message);
            },
            error: function () {
                alert("There was error uploading files!");
            }
        });
    });
});

Comments

0

My StudentViewModel is like

public class StudentViewModel{
   public int Id { get; set; }
   public IFormFile StudentFile{ get; set; }
}

I have a Controller Action As

public IActionResult UploadFiles(List<StudentViewModel> studentViewModel)
{

}

.

$(function () {
    $("#btnEventFilesUpload").click(function (evt) {
        
var formData = new FormData();
for (var j = 0; j < myValues.length; j++) {
var files = document.getElementById('File' + j);
formData.append('studentViewModel[' + j + '].Id', 1);
formData.append('studentViewModel[' + j +'].StudentFile', files[0]);
}
        $.ajax({
            type: "POST",
            url: "/Event/UploadFiles",
            contentType: false,
            processData: false,
            data: formData ,
            success: function (message) {
                alert(message);
            },
            error: function () {
                alert("There was error uploading files!");
            }
        });
    });
});

1 Comment

Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.