Bagaimana cara mengirim ViewModel dan file dalam satu permintaan Ajax POST, di MVC 5?

Saya memiliki aplikasi ASP.NET MVC 5. Dan saya mencoba mengirim permintaan POST dengan data Model, dan juga menyertakan file yang dipilih pengguna. Ini ViewModel saya (disederhanakan agar lebih jelas):

public class Model
{
    public string Text { get; set; }
    public long Id { get; set; }
}

Inilah Aksi pengontrolnya:

[HttpPost]
public ActionResult UploadFile(long userId, Model model)
{
    foreach (string file in Request.Files)
    {
        // process files
    }

    return View("Index");
}

Elemen masukan HTML:

<div>
    <input type="file" name="UploadFile" id="txtUploadFile" />
</div>

Dan kode JavaScriptnya:

$('#txtUploadFile').on('change', function (e) {
    var data = new FormData();
    for (var x = 0; x < files.length; x++) {
        data.append("file" + x, files[x]);
    }
    data.append("userId", 1);
    data.append("model", JSON.stringify({ Text: 'test text', Id: 3 }));

    $.ajax({
        type: "POST",
        url: '/Home/UploadFile',
        contentType: false,
        processData: false,
        data: data,
        success: function (result) { },
        error: function (xhr, status, p3, p4) { }
    });
});

Masalahnya adalah ketika Permintaan mencapai tindakan pengontrol, saya memiliki file dan 'userId' yang terisi, tetapi parameter 'model' selalu nol. Apakah saya melakukan kesalahan saat mengisi objek FormData?


person Igor Goroshko    schedule 26.09.2015    source sumber
comment
Dengan contentType: application/json tidak akan mengirim file.   -  person Igor Goroshko    schedule 27.09.2015
comment
Lihat jawaban ini - alih-alih data.append("model", JSON.stringify({ Text: 'test text', Id: 3 }));, seharusnya data.append(Text, 'test text'); data.append(Id, 3);   -  person    schedule 27.09.2015
comment
Terima kasih, sekarang saya mengerti apa masalahnya dengan FormData!   -  person Igor Goroshko    schedule 27.09.2015


Jawaban (1)


Inilah yang saya uji gunakan dengan MVC5 dan IE11/chrome

Lihat

<script>
    $(function () {
        $("#form1").submit(function () {
            /*You can also inject values to suitable named hidden fields*/
            /*You can also inject the whole hidden filed to form dynamically*/
            $('#name2').val(Date); 
            var formData = new FormData($(this)[0]);
            $.ajax({
                url: $(this).attr('action'),
                type: $(this).attr('method'),
                data: formData,
                async: false,
                success: function (data) {
                    alert(data)
                },
                error: function(){
                    alert('error');
                },
                cache: false,
                contentType: false,
                processData: false
            });
            return false;
        });
    });
</script>

<form id="form1" action="/Home/Index" method="post" enctype="multipart/form-data">
    <input type="text" id="name1" name="name1" value="value1" />
    <input type="hidden" id ="name2" name="name2" value="" />
    <input name="file1" type="file" />
    <input type="submit" value="Sublit" />
</form>

Pengontrol

public class HomeController : Controller
{
    [HttpGet]
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase file1, string name1, string name2)
    {
        var result = new List<string>();
        if (file1 != null)
            result.Add(string.Format("{0}: {1} bytes", file1.FileName, file1.ContentLength));
        else
            result.Add("No file");
        result.Add(string.Format("name1: {0}", name1));
        result.Add(string.Format("name2: {0}", name2));
        return Content(string.Join(" - ", result.ToArray()));
    }
}

Terima kasih kepada Silver89 atas jawabannya

person Reza Aghaei    schedule 26.09.2015
comment
Masalahnya adalah saya tidak memiliki semua bidang yang wajib diisi pada formulir, sehingga Model dibuat dalam kode JS, tepat sebelum mengirim permintaan POST. - person Igor Goroshko; 27.09.2015
comment
@IgorGoroshko Saya rasa ada banyak cara untuk mengatasi masalah ini, salah satu yang dapat Anda uji adalah dengan memasukkan nilai Anda ke dalam bidang formulir tersembunyi bernama yang sesuai. - person Reza Aghaei; 27.09.2015
comment
@IgorGoroshko Diperbarui untuk memasukkan nilai di bidang tersembunyi. - person Reza Aghaei; 27.09.2015
comment
Terima kasih, ini berhasil, tetapi masalah dalam kode saya adalah kami memiliki fungsi JS, yang menerima Model sebagai parameter. Fungsi ini bertanggung jawab untuk menemukan file dalam kelompok elemen input:file dan mengirimkannya bersama dengan model, sehingga kita tidak memiliki akses ke elemen form. - person Igor Goroshko; 27.09.2015
comment
@IgorGoroshko seperti yang saya katakan ada banyak cara untuk melakukan itu, misalnya data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); - person Reza Aghaei; 27.09.2015
comment
@IgorGoroshko Saya rasa ini adalah jawaban dari pertanyaan Bagaimana cara mengirim ViewModel dan file dalam satu permintaan Ajax POST, di MVC 5? dan dapat diterima agar lebih berguna bagi pengguna di masa mendatang :) - person Reza Aghaei; 27.09.2015
comment
Ya terima kasih banyak! Saya telah melihat semua pendekatan, dan akhirnya memutuskan untuk membuat FormData secara terprogram. - person Igor Goroshko; 27.09.2015