จะโพสต์อาร์เรย์ของวัตถุที่ซับซ้อนด้วย JSON, jQuery ไปยัง ASP.NET MVC Controller ได้อย่างไร


92

รหัสปัจจุบันของฉันมีลักษณะดังต่อไปนี้ ฉันจะส่งอาร์เรย์ของฉันไปยังคอนโทรลเลอร์ได้อย่างไรและการกระทำของคอนโทรลเลอร์ของฉันต้องยอมรับพารามิเตอร์ประเภทใด

function getplaceholders() {
    var placeholders = $('.ui-sortable');
    var result = new Array();
    placeholders.each(function() {
        var ph = $(this).attr('id');
        var sections = $(this).find('.sort');
        var section;

        sections.each(function(i, item) {
            var sid = $(item).attr('id');

            result.push({ 'SectionId': sid, 'Placeholder': ph, 'Position': i });
        });
    });
    alert(result.toString());
    $.post(
        '/portal/Designer.mvc/SaveOrUpdate',
        result,
        function(data) {
            alert(data.Result);
        }, "json");
};

วิธีการดำเนินการควบคุมของฉันดูเหมือน

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

คำตอบ:


84

ฉันพบวิธีแก้ปัญหาแล้ว ผมใช้วิธีการแก้ปัญหาของสตีฟคนต่างชาติเป็นjQuery และ ASP.NET MVC - ส่ง JSON เพื่อการกระทำ - เยือน

รหัสมุมมอง ASP.NET MVC ของฉันดูเหมือนว่า:

function getplaceholders() {
        var placeholders = $('.ui-sortable');
        var results = new Array();
        placeholders.each(function() {
            var ph = $(this).attr('id');
            var sections = $(this).find('.sort');
            var section;

            sections.each(function(i, item) {
                var sid = $(item).attr('id');
                var o = { 'SectionId': sid, 'Placeholder': ph, 'Position': i };
                results.push(o);
            });
        });
        var postData = { widgets: results };
        var widgets = results;
        $.ajax({
            url: '/portal/Designer.mvc/SaveOrUpdate',
            type: 'POST',
            dataType: 'json',
            data: $.toJSON(widgets),
            contentType: 'application/json; charset=utf-8',
            success: function(result) {
                alert(result.Result);
            }
        });
    };

และแอคชันคอนโทรลเลอร์ของฉันตกแต่งด้วยแอตทริบิวต์ที่กำหนดเอง

[JsonFilter(Param = "widgets", JsonDataType = typeof(List<PageDesignWidget>))]
public JsonResult SaveOrUpdate(List<PageDesignWidget> widgets

โค้ดสำหรับแอตทริบิวต์ที่กำหนดเองสามารถพบได้ที่นี่ (ตอนนี้ลิงก์เสีย)

เนื่องจากลิงก์เสียนี่คือรหัสสำหรับ JsonFilterAttribute

public class JsonFilter : ActionFilterAttribute
{
    public string Param { get; set; }
    public Type JsonDataType { get; set; }
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
        {
            string inputContent;
            using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
            {
                inputContent = sr.ReadToEnd();
            }
            var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
            filterContext.ActionParameters[Param] = result;
        }
    }
}

JsonConvert.DeserializeObject มาจาก Json.NET

ลิงค์: Serializing และ Deserializing JSON ด้วย Json.NET


ดูดีมาก - บล็อกโพสต์และลิงก์โค้ดแอตทริบิวต์ที่กำหนดเองไม่ทำงานอีกต่อไป - คุณสามารถโพสต์ใหม่ได้หรือไม่
littlechris

4
โซลูชันนี้ต้องการการเปลี่ยนแปลงในฝั่งไคลเอ็นต์และเซิร์ฟเวอร์ ฉันรู้ว่าคุณต้องการสิ่งนี้มานานแล้ว แต่ฉันอาจให้ลิงก์ไปยังแนวทางอื่นด้วยเช่นกันซึ่งใช้ปลั๊กอิน jQuery แบบธรรมดาที่ทำให้สามารถแปลงวัตถุ Javascript ใด ๆ ให้เป็นรูปแบบที่ตัวประสานโมเดลเริ่มต้นเข้าใจและโมเดลเชื่อมโยงกับพารามิเตอร์ ไม่จำเป็นต้องใช้ตัวกรอง erraticdev.blogspot.com/2010/12/…ฉันไม่รู้ว่าคุณแก้ไขข้อผิดพลาดในการตรวจสอบความถูกต้องได้อย่างไร แต่ฉันมีวิธีแก้ไขเช่นกัน: erraticdev.blogspot.com/2010/11/…
Robert Koritnik

3
คุณสามารถให้ที่มา / ที่มาของ JavaScriptConvert.DeserializeObject ได้ไหม
Matthieu

มันคือไลบรารี Newtonsoft Json - หากคุณเปิดตัวจัดการแพ็คเกจ nuget และค้นหาใน Newtonsoft มันจะแสดงให้คุณเห็น (ตอนนี้มันเป็นปี 2016) อาจจะเห็นได้ชัดในตอนนี้ แต่ในกรณีที่ใครสงสัย
Robb Sadler

22

ตัวกรองการดำเนินการ jquery stringify bleh ...

Peter ฟังก์ชันนี้เป็นของ MVC นั่นเป็นสิ่งหนึ่งที่ทำให้ MVC ยอดเยี่ยมมาก

$.post('SomeController/Batch', { 'ids': ['1', '2', '3']}, function (r) {
   ...
});

และในการดำเนินการ

[HttpPost]
public ActionResult Batch(string[] ids)
{
}

ทำงานได้อย่างมีเสน่ห์:

ป้อนคำอธิบายภาพที่นี่

หากคุณใช้ jQuery 1.4+ คุณต้องการตรวจสอบการตั้งค่าโหมดดั้งเดิม:

jQuery.ajaxSettings.traditional = true;

ตามที่อธิบายไว้ที่นี่: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

สิ่งนี้ใช้ได้กับวัตถุที่ซับซ้อน หากคุณสนใจคุณควรดูเอกสาร MVC เกี่ยวกับ Model Binding: http://msdn.microsoft.com/en-us/library/dd410405.aspx


1
คุณอาจจะพูดถูก แต่ตัวประสานโมเดล JSON ยังใหม่สำหรับ MVC3 และคำถามถูกถามในปี 2008 เมื่อสิ่งนี้ไม่ได้รับการสนับสนุน มันจะคุ้มค่าที่จะกล่าวถึงในคำตอบของคุณ
Piotr Owsiak

3
นี่เป็นตัวอย่างของการส่งอาร์เรย์ของวัตถุที่ซับซ้อนได้อย่างไร?
DuckMaestro

ไม่ใช่ แต่ตัวอย่างยังคงใช้ (MVC 3+) ตราบใดที่ชื่อพารามิเตอร์ของคุณตรงกับโมเดลที่คุณคาดหวังคุณจะไม่มีปัญหาใด ๆ
เจมิทเชลล์

คีย์ในที่นี้คือการสร้างออบเจ็กต์ JSON ด้วยชื่อพารามิเตอร์เมธอด ("ids") จากนั้นใส่อาร์เรย์ของอ็อบเจ็กต์ที่ซับซ้อนภายในนั้น นอกจากนี้ให้กำหนดพารามิเตอร์ที่สามเป็น "จริง" และคุณจะดูแลโหมดดั้งเดิม
redwards510

11

ใน.NET4.5, MVC 5จำเป็นที่จะต้องไม่มีเครื่องมือ

Javascript:

วัตถุใน JS: ป้อนคำอธิบายภาพที่นี่

กลไกที่โพสต์

    $('.button-green-large').click(function() {
        $.ajax({
            url: 'Quote',
            type: "POST",
            dataType: "json",
            data: JSON.stringify(document.selectedProduct),
            contentType: 'application/json; charset=utf-8',
        });
    });

ค#

วัตถุ:

public class WillsQuoteViewModel
{
    public string Product { get; set; }

    public List<ClaimedFee> ClaimedFees { get; set; }
}

public partial class ClaimedFee //Generated by EF6
{
    public long Id { get; set; }
    public long JourneyId { get; set; }
    public string Title { get; set; }
    public decimal Net { get; set; }
    public decimal Vat { get; set; }
    public string Type { get; set; }

    public virtual Journey Journey { get; set; }
}

ตัวควบคุม:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Quote(WillsQuoteViewModel data)
{
....
}

ได้รับวัตถุ:

ป้อนคำอธิบายภาพที่นี่

หวังว่านี่จะช่วยคุณประหยัดเวลาได้บ้าง


8

ในช่วงครึ่งหลังของCreate REST API โดยใช้ ASP.NET MVC ที่พูดทั้ง JSON และ XML ธรรมดาเพื่ออ้างอิง:

ตอนนี้เราต้องยอมรับเพย์โหลด JSON และ XML ซึ่งส่งผ่าน HTTP POST บางครั้งลูกค้าของคุณอาจต้องการอัปโหลดชุดของวัตถุในภาพเดียวสำหรับการประมวลผลชุดงาน ดังนั้นพวกเขาสามารถอัปโหลดวัตถุโดยใช้รูปแบบ JSON หรือ XML ไม่มีการสนับสนุนดั้งเดิมใน ASP.NET MVC เพื่อแยกวิเคราะห์ JSON หรือ XML ที่โพสต์โดยอัตโนมัติและแมปกับพารามิเตอร์ Action โดยอัตโนมัติ ฉันจึงเขียนฟิลเตอร์ที่ทำได้ "

จากนั้นเขาใช้ตัวกรองการดำเนินการที่แมปวัตถุ JSON กับ C # พร้อมรหัสที่แสดง


ฉันแค่เขียน anwser ของฉัน แต่ฉันจะโพสต์ต่อไป ;-)
JSC

7

ก่อนอื่นให้ดาวน์โหลดโค้ด JavaScript JSON2.jsซึ่งจะช่วยให้เราจัดลำดับวัตถุให้เป็นสตริง

ในตัวอย่างของฉันฉันโพสต์แถวของjqGridผ่าน Ajax:

    var commissions = new Array();
    // Do several row data and do some push. In this example is just one push.
    var rowData = $(GRID_AGENTS).getRowData(ids[i]);
    commissions.push(rowData);
    $.ajax({
        type: "POST",
        traditional: true,
        url: '<%= Url.Content("~/") %>' + AREA + CONTROLLER + 'SubmitCommissions',
        async: true,
        data: JSON.stringify(commissions),
        dataType: "json",
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            if (data.Result) {
                jQuery(GRID_AGENTS).trigger('reloadGrid');
            }
            else {
                jAlert("A problem ocurred during updating", "Commissions Report");
            }
        }
    });

ตอนนี้บนคอนโทรลเลอร์:

    [HttpPost]
    [JsonFilter(Param = "commissions", JsonDataType = typeof(List<CommissionsJs>))]
    public ActionResult SubmitCommissions(List<CommissionsJs> commissions)
    {
        var result = dosomething(commissions);
        var jsonData = new
        {
            Result = true,
            Message = "Success"
        };
        if (result < 1)
        {
            jsonData = new
            {
                Result = false,
                Message = "Problem"
            };
        }
        return Json(jsonData);
    }

สร้างคลาส JsonFilter (ขอบคุณการอ้างอิง JSC)

    public class JsonFilter : ActionFilterAttribute
    {
        public string Param { get; set; }
        public Type JsonDataType { get; set; }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (filterContext.HttpContext.Request.ContentType.Contains("application/json"))
            {
                string inputContent;
                using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream))
                {
                    inputContent = sr.ReadToEnd();
                }
                var result = JsonConvert.DeserializeObject(inputContent, JsonDataType);
                filterContext.ActionParameters[Param] = result;
            }
        }
    }

สร้างคลาสอื่นเพื่อให้ตัวกรองสามารถแยกวิเคราะห์สตริง JSON กับอ็อบเจ็กต์ที่ปรับเปลี่ยนได้จริง: คลาส comissionsJS นี้เป็นแถวทั้งหมดของ jqGrid ของฉัน

    public class CommissionsJs
    {
        public string Amount { get; set; }

        public string CheckNumber { get; set; }

        public string Contract { get; set; }
        public string DatePayed { get; set; }
        public string DealerName { get; set; }
        public string ID { get; set; }
        public string IdAgentPayment { get; set; }
        public string Notes { get; set; }
        public string PaymentMethodName { get; set; }
        public string RowNumber { get; set; }
        public string AgentId { get; set; }
    }

ฉันหวังว่าตัวอย่างนี้จะช่วยอธิบายวิธีการโพสต์วัตถุที่ซับซ้อน



-1

โอ้พระเจ้า. ไม่จำเป็นต้องทำอะไรเป็นพิเศษ เฉพาะในส่วนโพสต์ของคุณให้ทำดังนี้:

    $.post(yourURL,{ '': results})(function(e){ ...}

ในเซิร์ฟเวอร์ใช้สิ่งนี้:

   public ActionResult MethodName(List<yourViewModel> model){...}

ลิงค์นี้ช่วยคุณทำ ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.