จะส่ง ViewModel และไฟล์ในคำขอ Ajax POST เดียวใน MVC 5 ได้อย่างไร

ฉันมีแอปพลิเคชัน ASP.NET MVC 5 และฉันกำลังพยายามส่งคำขอ POST พร้อมข้อมูล Model และรวมไฟล์ที่ผู้ใช้เลือกด้วย นี่คือ ViewModel ของฉัน (ย่อให้ง่ายขึ้นเพื่อความชัดเจน):

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

นี่คือการกระทำของคอนโทรลเลอร์:

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

    return View("Index");
}

องค์ประกอบอินพุต Html:

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

และโค้ด JavaScript:

$('#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) { }
    });
});

ปัญหาคือเมื่อคำขอไปถึงการกระทำของคอนโทรลเลอร์ ฉันมีไฟล์และ 'userId' ที่เติมข้อมูล แต่พารามิเตอร์ 'model' จะเป็นโมฆะเสมอ ฉันทำอะไรผิดเมื่อเติมวัตถุ FormData หรือไม่


person Igor Goroshko    schedule 26.09.2015    source แหล่งที่มา
comment
ด้วย contentType: application/json มันจะไม่ส่งไฟล์   -  person Igor Goroshko    schedule 27.09.2015
comment
อ้างอิง คำตอบนี้ - แทนที่จะเป็น data.append("model", JSON.stringify({ Text: 'test text', Id: 3 })); ควรเป็น data.append(Text, 'test text'); data.append(Id, 3);   -  person    schedule 27.09.2015
comment
ขอบคุณ ตอนนี้ฉันรู้แล้วว่าปัญหาของ FormData คืออะไร!   -  person Igor Goroshko    schedule 27.09.2015


คำตอบ (1)


นี่คือสิ่งที่ฉันทดสอบโดยใช้ MVC5 และ IE11 / chrome

ดู

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

ตัวควบคุม

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

ขอขอบคุณ Silver89 สำหรับคำตอบ

person Reza Aghaei    schedule 26.09.2015
comment
ปัญหาคือฉันไม่มีฟิลด์ที่จำเป็นทั้งหมดในแบบฟอร์ม ดังนั้น Model จึงถูกสร้างขึ้นในโค้ด JS ก่อนที่จะส่งคำขอ POST - person Igor Goroshko; 27.09.2015
comment
@IgorGoroshko ฉันคิดว่ามีหลายวิธีในการแก้ปัญหานี้ วิธีที่คุณสามารถทดสอบได้คือการฉีดค่าของคุณในฟิลด์รูปแบบที่ซ่อนอยู่ซึ่งมีชื่อเหมาะสม - person Reza Aghaei; 27.09.2015
comment
@IgorGoroshko อัปเดตเพื่อฉีดค่าในฟิลด์ที่ซ่อนอยู่ - person Reza Aghaei; 27.09.2015
comment
ขอบคุณ ใช้งานได้ แต่ปัญหาในโค้ดของฉันคือเรามีฟังก์ชัน JS ซึ่งยอมรับ Model เป็นพารามิเตอร์ ฟังก์ชันนี้มีหน้าที่ค้นหาไฟล์ในกลุ่มขององค์ประกอบ input:file และส่งไฟล์เหล่านั้นพร้อมกับโมเดล ดังนั้นเราจึงไม่สามารถเข้าถึงองค์ประกอบแบบฟอร์มได้ - person Igor Goroshko; 27.09.2015
comment
@IgorGoroshko อย่างที่ฉันบอกว่ามีหลายวิธีในการทำเช่นนั้น data = new FormData(); data.append( 'file', $( '#file' )[0].files[0] ); - person Reza Aghaei; 27.09.2015
comment
@IgorGoroshko ฉันคิดว่านี่คือคำตอบของคำถาม จะส่ง ViewModel และไฟล์ในคำขอ Ajax POST เดียวใน MVC 5 ได้อย่างไร และกรุณาได้รับการยอมรับว่ามีประโยชน์มากขึ้นสำหรับผู้ใช้ในอนาคต :) - person Reza Aghaei; 27.09.2015
comment
ใช่ ขอบคุณมาก! ฉันกำลังดูวิธีการทั้งหมด และในที่สุดก็ตัดสินใจสร้าง FormData โดยทางโปรแกรม - person Igor Goroshko; 27.09.2015