ฉันจะยอมรับอาร์เรย์เป็นพารามิเตอร์การดำเนินการของคอนโทรลเลอร์ ASP.NET MVC ได้อย่างไร


86

ฉันมีตัวควบคุม ASP.net MVC ที่เรียกDesignsว่ามีการดำเนินการพร้อมลายเซ็นต่อไปนี้:

public ActionResult Multiple(int[] ids)

อย่างไรก็ตามเมื่อฉันพยายามนำทางไปยังการกระทำนี้โดยใช้ url:

http://localhost:54119/Designs/Multiple?ids=24041,24117

idsพารามิเตอร์เป็นโมฆะเสมอ มีวิธีใดบ้างที่จะรับ MVC เพื่อแปลง?ids=พารามิเตอร์การสืบค้น URL เป็นอาร์เรย์สำหรับการดำเนินการ ฉันเคยเห็นการพูดถึงการใช้ตัวกรองการดำเนินการ แต่เท่าที่ฉันสามารถบอกได้ว่าจะใช้ได้เฉพาะกับ POST ที่อาร์เรย์ถูกส่งผ่านในข้อมูลคำขอแทนที่จะเป็นใน URL

คำตอบ:


153

ตัวยึดรูปแบบเริ่มต้นต้องการ url นี้:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

เพื่อที่จะเชื่อมโยงกับ:

public ActionResult Multiple(int[] ids)
{
    ...
}

และถ้าคุณต้องการให้สิ่งนี้ทำงานกับค่าที่คั่นด้วยลูกน้ำคุณสามารถเขียนตัวประสานโมเดลที่กำหนดเอง:

public class IntArrayModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (value == null || string.IsNullOrEmpty(value.AttemptedValue))
        {
            return null;
        }

        return value
            .AttemptedValue
            .Split(',')
            .Select(int.Parse)
            .ToArray();
    }
}

จากนั้นคุณสามารถใช้ตัวยึดแบบจำลองนี้กับอาร์กิวเมนต์การดำเนินการเฉพาะ:

public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
    ...
}

หรือนำไปใช้ทั่วโลกเพื่อพารามิเตอร์จำนวนเต็มอาร์เรย์ทั้งหมดในของคุณApplication_StartในGlobal.asax:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());

และตอนนี้การกระทำของคอนโทรลเลอร์ของคุณอาจมีลักษณะดังนี้:

public ActionResult Multiple(int[] ids)
{
    ...
}

2
[FromUri]ฉันถูกหายไป public ActionResult Multiple([FromUri]int[] ids) {} (GET)
C0d1ngJammer

1
@ ดารินมีวิธีใช้การผูกแบบกำหนดเองทั่วโลก แต่เพิกเฉยสำหรับการดำเนินการเฉพาะหรือไม่? ฉันหาวิธีทำไม่ได้: stackoverflow.com/questions/45379040/…
akd

15

หากต้องการขยายคำตอบของ Darin Dimitrovสิ่งที่คุณสามารถหลีกเลี่ยงได้คือการยอมรับstringพารามิเตอร์ URL ของคุณและแปลงเป็นอาร์เรย์ด้วยตัวคุณเอง:

public ActionResult Multiple(string ids){
  int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
  /* ...process results... */
}

หากคุณได้รับข้อผิดพลาดในการแยกวิเคราะห์ขณะทำสิ่งนี้ (เนื่องจากมีคนส่งอาร์เรย์ที่ผิดรูปแบบไปให้คุณ) คุณสามารถทำให้ตัวจัดการข้อยกเว้นของคุณส่งคืน400 Bad Requestข้อผิดพลาดแทนค่าเริ่มต้นซึ่งเป็น404 Not Foundข้อผิดพลาดที่ไม่เป็นมิตรมากขึ้นซึ่ง MVC จะส่งกลับเมื่อไม่พบจุดสิ้นสุด


9

คุณยังสามารถใช้รูปแบบ URL นี้ได้และ ASP.NET MVC จะทำทุกอย่างให้คุณ แต่อย่าลืมใช้การเข้ารหัส URL

?param1[0]=3344&param1[1]=2222

6

ฉันไม่รู้ว่าสตริง URL ของ Groky มาจากไหน แต่ฉันมีปัญหาเดียวกันกับจาวาสคริปต์บางตัวที่เรียกคอนโทรลเลอร์ / การกระทำของฉัน มันจะสร้าง URL เป็นnull1 หรือ "ID" จำนวนมากจากรายการที่เลือกได้หลายรายการ (ซึ่งไม่ซ้ำกับโซลูชันที่ฉันจะแชร์)

ฉันคัดลอก / วางแฟ้มประสานโมเดลที่กำหนดเองของ Darin และตกแต่งการกระทำ / พารามิเตอร์ของฉัน แต่มันไม่ได้ผล ฉันยังคงมีมูลค่าnull int[] idsแม้ในกรณี "ปลอดภัย" ที่ฉันมีหลาย ID

ฉันลงเอยด้วยการเปลี่ยนจาวาสคริปต์เพื่อสร้างอาร์เรย์พารามิเตอร์ที่เป็นมิตรกับ ASP.NET MVC เช่น

?ids=1&ids=2

ฉันต้องทำอะไรโง่ ๆ

ids || []                 #=> if null, get an empty array
[ids || []]               #=> if a single item, wrap it in an array
[].concat.apply([], ...)  #=> in case I wrapped an array, flatten it

ดังนั้นบล็อกเต็มคือ

ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')

มันยุ่ง แต่เป็นครั้งแรกที่ฉันต้องแฮ็คแบบนี้ในจาวาสคริปต์


2
แค่อยากรู้ว่ามี "not" ก่อน "ครั้งแรก" ในประโยคสุดท้ายนั้นหายไปหรือไม่ มิฉะนั้นคุณโชคดี!
DCShannon

1
@DCShannon: ฮ่าฮ่าฉันเห็นจุดของคุณ! แต่นี่เป็นครั้งแรกของฉัน ฉันไม่แน่ใจว่าเรื่องแบบนี้เป็นเรื่องปกติหรือว่าฉันกำลังจะลงน้ำ
Anthony Mastrean

1

.Net Core คำตอบ

สำหรับผู้ที่มาที่นี่ในช่วงเวลาที่ผ่านมาคุณสามารถทำได้ใน. Net Core ด้วย:

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

และ:

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