ส่งอาร์เรย์ไปยัง mvc Action ผ่าน AJAX


124

ฉันกำลังพยายามส่งอาร์เรย์ (หรือ IEnumerable) ของ ints จากผ่าน AJAX ไปยังการดำเนินการ MVC และฉันต้องการความช่วยเหลือเล็กน้อย

จาวาสคริปต์คือ

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {...

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

public ActionResult MyAction(IEnumerable<int> arrayOfValues )

ในขณะนี้คำขอถูกจัดรูปแบบเป็น

controller/MyAction?_=1301503418429&arrayOfValues[]=491&arrayOfValues[]=368&arrayOfValues[]=235&arrayOfValues[]=437

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

ขอบคุณมากสำหรับความช่วยเหลือของคุณ

เดฟ

คำตอบ:


149

ตั้งค่าคุณสมบัติดั้งเดิมเป็นจริงก่อนทำการรับสาย เช่น:

jQuery.ajaxSettings.traditional = true

$.get('/controller/MyAction', { vals: arrayOfValues }, function (data) {... 

3
ขอบคุณ! คุณช่วยอธิบายความแตกต่างระหว่าง ajax แบบดั้งเดิมและไม่ใช่แบบดั้งเดิมได้ไหม ฉันต้องการทำความเข้าใจให้ดีขึ้นว่าฉันกำลังทำอะไรกับแอปพลิเคชันที่เหลือของฉัน
Tom Beech

5
คุณยังสามารถเพิ่มการตั้งค่าแบบเดิมในการโทรครั้งเดียว จากนั้นจะไม่ส่งผลกระทบต่อส่วนที่เหลือ
Gluip

1
คำตอบนี้ถูกต้อง แต่ถ้าคุณต้องการตั้งค่า "ดั้งเดิม" สำหรับการตรวจสอบการโทรครั้งเดียว @RionWilliams โหวตทั้งคู่ ขอบคุณ!
kzfabi

@Tom Beech ในขณะที่ jQuery 1.4 วิธี $ .param () จะทำให้วัตถุแบบลึกเป็นอนุกรมแบบวนซ้ำเพื่อรองรับภาษาและกรอบการเขียนสคริปต์สมัยใหม่เช่น PHP และ Ruby on Rails คุณสามารถปิดใช้งานฟังก์ชันนี้ได้ทั่วโลกโดยการตั้งค่า jQuery.ajaxSettings.traditional = true;
Alexey Shevelyov

คำตอบเหล่านี้ไม่ได้ผลสำหรับฉัน (อาจเป็นเพราะคอนโทรลเลอร์ของฉันเป็นตัวควบคุม API หรือไม่) แต่ฉันพบวิธีแก้ปัญหาของฉันในคำตอบ SO ต่อไปนี้: stackoverflow.com/a/11100414/1751792
Lopsided

119

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

 var arrayOfValues = new Array();

 //Populate arrayOfValues 
 $.ajax({ 
      type: "POST",
      url: "<%= Url.Action("MyAction","Controller")%>",
      traditional: true,
      data: { 'arrayOfValues': arrayOfValues }              
 });

4
ซึ่งดีกว่าการตั้งค่าทั่วโลกแบบสุ่มสี่สุ่มห้าในไฟล์ web.config อย่างที่บางคนแนะนำ อีกฝ่ายมีโอกาสดีๆของตัวเอง แต่ของคุณควรเป็นโซลูชันเริ่มต้น
Panzercrisis

นี่เป็นเพียงการส่งข้อมูลเป็นพารามิเตอร์ไปยัง ActionResult มันจะเรียกโค้ด Inside ActionResult หรือไม่ ตัวอย่างเช่นหากมีโค้ดที่จะแทรก arrayofvalues ​​ลงในฐานข้อมูลโค้ดนั้นจะทำงานหรือไม่
Saurabh

สิ่งนี้แก้ไขสิ่งที่ฉันต้องการได้อย่างแท้จริง อาร์เรย์ของฉันยังคงกลับมาเป็นโมฆะในคอนโทรลเลอร์ของฉันจนกว่าฉันจะเพิ่มสิ่งนี้และรับไว้ในคอนโทรลเลอร์ของฉันเช่นอาร์เรย์ <string> IEnumerable
SeanMC

52

ค่อนข้างช้า แต่คำตอบที่แตกต่างกันสำหรับคำตอบที่มีอยู่แล้วที่นี่:

หาก$.ajaxคุณต้องการใช้ฟังก์ชันชวเลขแทน$.getหรือ$.postคุณสามารถส่งอาร์เรย์ด้วยวิธีนี้:


ชวเลขได้รับ

var array = [1, 2, 3, 4, 5];
$.get('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}

โพสต์ชวเลข

var array = [1, 2, 3, 4, 5];
$.post('/controller/MyAction', $.param({ data: array }, true), function(data) {});


// Action Method
[HttpPost]
public void MyAction(List<int> data)
{
    // do stuff here
}


หมายเหตุ:

  • พารามิเตอร์บูลีนใน$.paramมีไว้สำหรับ traditionalคุณสมบัติซึ่งต้องเป็นtrueค่านี้จึงจะทำงานได้

2
ขอบคุณสำหรับเคล็ดลับเกี่ยวกับสถานที่ให้บริการแบบดั้งเดิม ฉันไม่สามารถเข้าใจได้ว่าเหตุใดพารามิเตอร์ C # ของฉันจึงเป็นโมฆะ ฉันพบว่าประเภท "int []" จะทำงานในวิธีการดำเนินการ C # ด้วย
Dan Randolph

9

คุณควรจะทำได้ดี:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify({
      myKey: myArray
   }),
   success: function(data) { /* Whatever */ }
});

วิธีการดำเนินการของคุณจะเป็นดังนี้:

public ActionResult(List<int> myKey)
{
    // Do Stuff
}

สำหรับคุณดูเหมือนว่าคุณต้องกำหนดค่าของคุณให้แน่น JSONValueProvider ใน MVC จะแปลงสิ่งนั้นกลับเป็น IE ที่ไม่สามารถคำนวณได้สำหรับคุณ


ขอบคุณสำหรับคำตอบ แต่ฉันคิดว่าดูเหมือนว่าฉันต้องตั้งค่าดั้งเดิมเป็นจริง มีการโหวตเพิ่มขึ้นเนื่องจากฉันคิดว่ามันจะได้ผลเช่นกัน
Dave

9

คำตอบสำหรับการใช้ตัวเลือก "ดั้งเดิม" นั้นถูกต้อง ฉันแค่ให้ข้อมูลพื้นฐานเพิ่มเติมสำหรับสิ่งนี้ผู้ที่ต้องการเรียนรู้เพิ่มเติม

จากเอกสาร jQuery:

สำหรับ jQuery 1.8 เมธอด $ .param () จะไม่ใช้ jQuery.ajaxSettings.traditional เป็นค่าเริ่มต้นอีกต่อไปและจะตั้งค่าเริ่มต้นเป็นเท็จ

คุณสามารถอ่านเพิ่มเติมได้ที่นี่: http://michaelsync.net/2012/04/05/tips-asp-net-mvc-javascriptserializer-3-questions-and-3-answers และ http://haacked.com/archive /2008/10/23/model-binding-to-a-list.aspx

HTH


2

หากสิ่งอื่นทั้งหมดล้มเหลว ...

ไม่มีคำตอบอื่นใดที่จะช่วยแก้ปัญหาของฉันได้ ฉันกำลังพยายามเรียกเมธอด GET จาก JavaScript ไปยังตัวควบคุม MVC Web API และส่งอาร์เรย์ของจำนวนเต็มเป็นพารามิเตอร์ภายในคำขอนั้น ฉันลองใช้วิธีแก้ปัญหาทั้งหมดที่นี่ แต่พารามิเตอร์บนคอนโทรลเลอร์ของฉันยังคงเป็น NULL (หรือไม่มีอะไรสำหรับผู้ใช้ VB ของคุณ)

ในที่สุดฉันก็พบวิธีแก้ปัญหาของฉันในโพสต์ SOอื่นและมันก็ง่ายมากแค่เพิ่ม[FromUri]คำอธิบายประกอบก่อนพารามิเตอร์อาร์เรย์ในคอนโทรลเลอร์ ( ฉันต้องโทรโดยใช้การตั้งค่า AJAX "ดั้งเดิม" เพื่อหลีกเลี่ยงคำอธิบายประกอบวงเล็บ ) ดูด้านล่างสำหรับรหัสจริงที่ฉันใช้ในแอปพลิเคชันของฉัน


ลายเซ็นผู้ควบคุม:

ลายเซ็นคอนโทรลเลอร์ หมายเหตุ: คำอธิบายประกอบใน C # จะเป็น [FromUri]


JavaScript:

$.get('/api/InventoryApi/GetBalanceField', $.param({productIds: [42], inventoryFormId: 5493, inventoryBalanceType: 'Beginning'},true)).done(function(data) {console.log(data);});

สตริง URL จริง:

http://randomhostname/api/InventoryApi/GetBalanceField?productIds=42&inventoryFormId=5493&inventoryBalanceType=Beginning

2

ช้าไปหน่อย แต่ฉันสามารถใช้โซลูชันของ SNag ต่อไปใน $ .ajax () นี่คือรหัสหากจะช่วยทุกคน:

var array = [1, 2, 3, 4, 5];

$.ajax({
    type: "GET",
    url: '/controller/MyAction',
    data: $.param({ data: array}, true),
    contentType: 'application/json; charset=utf-8',
    success: function (data) {
    },
    error: function (x, y, z) {
    }
});

// Action Method
public void MyAction(List<int> data)
{
    // do stuff here
}

1

หากคุณกำลังย้ายไปยัง ASP.NET Core MVC จาก. Net Framework MVC เหมือนที่ฉันเป็นอยู่สิ่งต่างๆมีการเปลี่ยนแปลงเล็กน้อย การเรียก ajax ต้องอยู่บนออบเจ็กต์ดิบโดยใช้ stringify ดังนั้นแทนที่จะส่งผ่านข้อมูล{ vals: arrayOfValues }ควรJSON.stringify(arrayOfValues)เป็นดังนี้:

$.ajax({
   url: 'controller/myaction',
   data: JSON.stringify(arrayOfValues),
   success: function(data) { /* Whatever */ }
});

การเปลี่ยนแปลงอื่น ๆ ที่เกิดขึ้นใน ASP.NET Core คือการป้องกันการปลอมแปลงคำขอข้ามไซต์ดังนั้นสำหรับการเรียกไปยังการดำเนินการ MVC จากเมธอด ajax [FromBody]จะต้องใช้ atribute กับพารามิเตอร์การดำเนินการดังนี้:

public ActionResult MyAction([FromBody] IEnumerable<int> arrayOfValues )

ขอบคุณสิ่งนี้มีประโยชน์อย่างไม่น่าเชื่อหลังจากการเปลี่ยนวิธีการส่งข้อมูลล้มเหลว!
NibblyPig

0

หากคุณใช้ASP.NET Core MVCและจำเป็นต้องจัดการกับวงเล็บเหลี่ยม (แทนที่จะใช้ตัวเลือก "ดั้งเดิม" ของ jQuery) ตัวเลือกเดียวที่ฉันพบคือการสร้างด้วยตนเองIEnumerableในเมธอด contoller

string arrayKey = "p[]=";
var pArray = HttpContext.Request.QueryString.Value
    .Split('&')
    .Where(s => s.Contains(arrayKey))
    .Select(s => s.Substring(arrayKey.Length));

0

ฉันทำงานกับasp.net core 2.2และ jquery และต้องส่งอ็อบเจ็กต์ที่ซับซ้อน ('คลาสหลัก') จากมุมมองไปยังคอนโทรลเลอร์ที่มีฟิลด์ข้อมูลอย่างง่ายและอาร์เรย์บางส่วน
ทันทีที่ฉันเพิ่มอาร์เรย์ในนิยาม c # 'คลาสหลัก' (ดูด้านล่าง) และส่งอาร์เรย์ (เติมที่ถูกต้อง) ผ่าน ajax (โพสต์) วัตถุทั้งหมดจะเป็นโมฆะในคอนโทรลเลอร์
อย่างแรกฉันคิดว่า "ดั้งเดิม: จริง" ที่ขาดหายไปสำหรับการโทร ajax ของฉันคือเหตุผล แต่นี่ไม่ใช่กรณี
ในกรณีของฉันเหตุผลคือคำจำกัดความใน c # 'main class'
ใน 'ชั้นเรียนหลัก' ฉันมี:

public List<EreignisTagNeu> oEreignistageNeu { get; set; }

และ EreignisTagNeu ถูกกำหนดให้เป็น:

public class EreignisTagNeu
{
 public int iHME_Key { get; set; } 
}

ฉันต้องเปลี่ยนคำจำกัดความใน 'คลาสหลัก' เป็น:

 public List<int> oEreignistageNeu { get; set; }

ตอนนี้ใช้งานได้แล้ว
ดังนั้น ... สำหรับฉันดูเหมือนว่าแกน asp.net มีปัญหา (พร้อมโพสต์) หากรายการสำหรับอาร์เรย์ไม่ได้กำหนดไว้อย่างสมบูรณ์ใน 'คลาสหลัก'
หมายเหตุ: ในกรณีของฉันสิ่งนี้ใช้ได้กับหรือไม่มี "ดั้งเดิม: จริง" สำหรับการโทร ajax


-3

คุณต้องแปลง Array เป็นสตริง:

//arrayOfValues = [1, 2, 3];  
$.get('/controller/MyAction', { arrayOfValues: "1, 2, 3" }, function (data) {...

ใช้งานได้แม้ในรูปแบบ int, long หรือ string

public ActionResult MyAction(int[] arrayOfValues )

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