ฉันจะโพสต์อาเรย์ของสตริงไปยัง ASP.NET MVC Controller โดยไม่มีฟอร์มได้อย่างไร


185

ฉันกำลังสร้างแอปขนาดเล็กเพื่อสอนตัวเอง ASP.NET MVC และ JQuery และหนึ่งในหน้าคือรายการที่สามารถเลือกได้บางรายการ จากนั้นฉันต้องการกดปุ่มและส่งรายการ (หรือสิ่งที่เทียบเท่า) ไปยังคอนโทรลเลอร์ของฉันที่มีรหัสของรายการที่เลือกโดยใช้ฟังก์ชั่นโพสต์ของ JQuery

ฉันจัดการเพื่อรับอาร์เรย์ที่มีรหัสขององค์ประกอบที่ถูกเลือกและตอนนี้ฉันต้องการโพสต์นั้น วิธีหนึ่งที่ฉันสามารถทำได้คือมีรูปแบบจำลองในหน้าของฉันพร้อมค่าที่ซ่อนอยู่จากนั้นตั้งค่าที่ซ่อนอยู่กับรายการที่เลือกและโพสต์แบบฟอร์มนั้น แม้ว่ามันจะดูสกปรก

มีวิธีที่สะอาดกว่านี้ในการทำสิ่งนี้โดยการส่งอาร์เรย์ไปยังคอนโทรลเลอร์โดยตรงหรือไม่? ฉันลองทำสิ่งต่าง ๆ เล็กน้อย แต่ดูเหมือนว่าคอนโทรลเลอร์ไม่สามารถแมปข้อมูลที่รับได้ นี่คือรหัสจนถึง:

function generateList(selectedValues) {
   var s = {
      values: selectedValues //selectedValues is an array of string
   };
   $.post("/Home/GenerateList", $.toJSON(s), function() { alert("back") }, "json");
}

จากนั้นผู้ควบคุมของฉันก็จะมีลักษณะเช่นนี้

public ActionResult GenerateList(List<string> values)
{
    //do something
}

สิ่งที่ฉันได้รับคือ "null" ในพารามิเตอร์คอนโทรลเลอร์ ...

เคล็ดลับใด ๆ


แม้ว่าคุณสามารถเข้าถึงข้อมูลเดียวกันได้โดยใช้Request["values[]"]
Tocco

คำตอบ:


247

ฉันแก้ไขคำตอบเพื่อรวมรหัสสำหรับแอปทดสอบที่ฉันทำ

อัปเดต: ฉันได้อัปเดต jQuery เพื่อตั้งค่า 'ดั้งเดิม' เป็นจริงเพื่อให้สามารถทำงานได้อีกครั้ง (ต่อ @DustinDavis 'คำตอบ)

ก่อนอื่นจาวาสคริปต์:

function test()
{
    var stringArray = new Array();
    stringArray[0] = "item1";
    stringArray[1] = "item2";
    stringArray[2] = "item3";
    var postData = { values: stringArray };

    $.ajax({
        type: "POST",
        url: "/Home/SaveList",
        data: postData,
        success: function(data){
            alert(data.Result);
        },
        dataType: "json",
        traditional: true
    });
}

และนี่คือรหัสในคลาสคอนโทรลเลอร์ของฉัน:

public JsonResult SaveList(List<String> values)
{
    return Json(new { Result = String.Format("Fist item in list: '{0}'", values[0]) });
}

เมื่อฉันเรียกฟังก์ชันจาวาสคริปต์นั้นฉันจะได้รับการแจ้งเตือนว่า "รายการแรกในรายการ: 'item1'" หวังว่านี่จะช่วยได้!


3
เป็นเรื่องที่ดีที่ฉันพบคำตอบนี้ตอนนี้ฉันสามารถส่งแถวของ Guid และการกระทำได้รับพวกเขาไปยังรายการ <Guid> ขอบคุณ
Tx3

43
มีสองสิ่งสำคัญที่ควรทราบที่นี่ 1) dataType: "json" 2.) แบบดั้งเดิม: จริงโดยที่พวกเขาจะไม่ถูกส่งผ่านไปยังวิธีการดำเนินการ
สตริง

1
โปรดทราบว่าdataType: 'JSON'ทำให้ jQuery พยายามแยกการตอบสนองเป็น JSON และจะเกิดข้อผิดพลาดหากไม่ถูกต้อง JSON
sennett

8
@Thanigainathan the dataType: 'json'สำหรับประเภท return และไม่จำเป็นต้องส่ง array ไปที่ Action contentType: "application/json; charset=utf-8"เป็นสิ่งหนึ่ง แต่ในบางกรณีเช่นนี้ไม่จำเป็น
Ruchan

1
ใช้ @emzerovar postData = { id: 45, [{myClassProp1: 1, myClassProp2: 2}, {}...], anotherParam: "some string" };
Nick M

108

FYI: JQuery เปลี่ยนวิธีการโพสต์ข้อมูลเป็นลำดับ

http://forum.jquery.com/topic/nested-param-serialization

คุณต้องตั้งค่า 'ดั้งเดิม' เป็นจริงฉลาดอื่น ๆ

{ Values : ["1", "2", "3"] }

จะออกมาเป็น

Values[]=1&Values[]=2&Values[]=3

แทน

Values=1&Values=2&Values=3

8
นี่คือบางสิ่งที่ทำให้ฉันต้องสะบัดหัวไปซักพัก การตั้งค่า$.ajax({ ..., traditional: true});จะช่วยให้กลับไปใช้การทำให้เป็นอันดับดั้งเดิม
juhan_h

ฉันต้องการสิ่งนี้เพื่อให้เส้นทาง ASP.NET MVC ใช้อาร์เรย์ js อย่างง่ายของค่าสตริง
BrandonG

คำตอบของคุณมีประโยชน์จริง ๆ ฉันมีสถานการณ์เดียวกัน intsแต่มันขึ้นอยู่กับ เมื่อฉันใช้traditional: trueมันใช้งานได้คำตอบและลิงก์ของคุณจะอธิบายถึงสาเหตุของมัน นอกจากนี้ยังทำงานเมื่อฉันใช้โดยไม่ต้องใช้type: "POST" traditional: trueทำไมถึงเป็นอย่างนั้น? คุณช่วยอธิบายได้ไหม FYI ฉันกำลังใช้ Asp.Net Mvc
barnes

มีวิธีใน ASP.NET ในการแยกอาร์เรย์แบบไม่ระบุชื่อเช่นนี้โดยไม่มีดัชนีหรือไม่? ค่า [] = 1 & ค่า [] = 2 & ค่า [] = 3
Charles Owen

24

ขอบคุณทุกคนสำหรับคำตอบ อีกโซลูชันที่รวดเร็วคือการใช้วิธีjQuery.paramด้วยพารามิเตอร์ดั้งเดิมที่ตั้งค่าเป็นจริงเพื่อแปลงวัตถุ JSON เป็นสตริง:

$.post("/your/url", $.param(yourJsonObject,true));

ทำงานได้ดีและติดตั้งได้อย่างสมบูรณ์แบบสำหรับฉันเนื่องจากฉันใช้ $ .post () แทนที่จะเป็น $ .ajax () ขอบคุณ !
หยุด

9

อย่าโพสต์ข้อมูลเป็นอาร์เรย์ ในการผูกเข้ากับรายการคู่คีย์ / ค่าควรถูกส่งด้วยค่าเดียวกันสำหรับแต่ละคีย์

คุณไม่ควรต้องการแบบฟอร์มในการทำเช่นนี้ คุณเพียงแค่ต้องการรายการคู่คีย์ / ค่าซึ่งคุณสามารถรวมไว้ในการเรียกไปยัง $ .post


3
ขอบคุณ อัปเดต URL คือ: haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Wiebe Tijsma

6

ใน.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)
{
....
}

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

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

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


4

การใช้งานอื่นที่ทำงานกับรายชื่อวัตถุไม่ใช่แค่สายอักขระ:

JS:

var postData = {};
postData[values] = selectedValues ;

$.ajax({
    url: "/Home/SaveList",
    type: "POST",
    data: JSON.stringify(postData),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(data){
        alert(data.Result);
    }
});

สมมติว่า 'selectValues' เป็น Array of Objects

ในคอนโทรลเลอร์พารามิเตอร์เป็นรายการของ ViewModels ที่เกี่ยวข้อง

public JsonResult SaveList(List<ViewModel> values)
{    
    return Json(new { 
          Result = String.Format("Fist item in list: '{0}'", values[0].Name) 
    });
}

1

ขณะที่ผมกล่าวถึงที่นี่ ,

หากคุณต้องการส่งต่อวัตถุ JSON ที่กำหนดเองไปยังการกระทำ MVC คุณสามารถใช้โซลูชันนี้ได้เช่นเดียวกับเครื่องราง

public string GetData() {
  // InputStream contains the JSON object you've sent
  String jsonString = new StreamReader(this.Request.InputStream).ReadToEnd();

  // Deserialize it to a dictionary
  var dic =
    Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < String,
    dynamic >> (jsonString);

  string result = "";

  result += dic["firstname"] + dic["lastname"];

  // You can even cast your object to their original type because of 'dynamic' keyword
  result += ", Age: " + (int) dic["age"];

  if ((bool) dic["married"])
    result += ", Married";

  return result;
}

ประโยชน์ที่แท้จริงของการแก้ปัญหานี้คือคุณไม่จำเป็นต้องกำหนดคลาสใหม่สำหรับการรวมกันของแต่ละอาร์กิวเมนต์และนอกจากนั้นคุณสามารถส่งวัตถุของคุณไปยังประเภทดั้งเดิมได้อย่างง่ายดาย

คุณสามารถใช้วิธีช่วยเหลือเช่นนี้เพื่อช่วยงานของคุณ:

public static Dictionary < string, dynamic > GetDic(HttpRequestBase request) {
  String jsonString = new StreamReader(request.InputStream).ReadToEnd();
  return Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < string, dynamic >> (jsonString);
}

0

คุณสามารถตั้งค่าพารามิเตอร์ส่วนกลางด้วย

jQuery.ajaxSettings.traditional = true;

-1

คำตอบช่วยฉันได้มากในสถานการณ์ของฉันดังนั้นขอบคุณสำหรับสิ่งนั้น อย่างไรก็ตามสำหรับคนอ้างอิงในอนาคตควรผูกกับแบบจำลองและตรวจสอบแล้ว โพสต์นี้จาก Phil Haack อธิบายสิ่งนี้สำหรับ MVC 2 http://haacked.com/archive/2010/04/15/sending-json-to-an-asp-net-mvc-action-method-argument.aspx

หวังว่านี่จะช่วยใครซักคน

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