ASP.NET MVC - ส่งผ่านพารามิเตอร์ไปยังคอนโทรลเลอร์


105

ฉันมีตัวควบคุมที่มีวิธีการดำเนินการดังนี้:

public class InventoryController : Controller
{
    public ActionResult ViewStockNext(int firstItem)
    {
        // Do some stuff
    }
}

และเมื่อฉันเรียกใช้ฉันได้รับข้อผิดพลาดระบุว่า:

พจนานุกรมพารามิเตอร์ไม่มีค่าที่ถูกต้องของประเภท 'System.Int32' สำหรับพารามิเตอร์ 'firstItem' ในการทำให้พารามิเตอร์เป็นทางเลือกประเภทควรเป็นประเภทอ้างอิงหรือประเภท Nullable

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

ฉันใช้ไวยากรณ์ url นี้เพื่อเรียกการดำเนินการ:

http://localhost:2316/Inventory/ViewStockNext/11

มีความคิดว่าทำไมฉันจึงได้รับข้อผิดพลาดนี้และฉันต้องทำอย่างไรเพื่อแก้ไข

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

คำตอบ:


106

การกำหนดเส้นทางของคุณต้องได้รับการตั้งค่าตามแนวของ{controller}/{action}/{firstItem}. ถ้าคุณปล่อยให้เส้นทางเป็นค่าเริ่มต้น{controller}/{action}/{id}ของคุณในไฟล์แล้วคุณจะต้องผ่านในglobal.asax.csid

routes.MapRoute(
    "Inventory",
    "Inventory/{action}/{firstItem}",
    new { controller = "Inventory", action = "ListAll", firstItem = "" }
);

... หรืออะไรที่ใกล้เคียง


44
หรือเปลี่ยนชื่อ "firstItem" เป็น "id"
Kyle Trauberman

8
พลัสโลกฉลาดที่จะเพิ่มวัตถุ จำกัด กับ MapRoute new { firstItem = @"\d" }เช่นดังนั้น: วิธีนี้ก็จะเพียงยอมรับถ้าพารามิเตอร์เป็นชนิดของหมายเลขใด ๆ คุณสามารถปรับเปลี่ยนนิพจน์ทั่วไปได้ตามต้องการและยัง จำกัด จำนวนทศนิยมได้ดังนี้new { firstItem = @"\d{4}" }- ตอนนี้สามารถมีความยาวได้เพียง 4 ตัวเลขเท่านั้น แก้ไข: ตัวอย่างของ MapRoute ที่แก้ไขทั้งหมด: jsfiddle.net/HJRgT
KristianB

86

คุณสามารถเปลี่ยน firstItem เป็น id และจะใช้งานได้

คุณสามารถเปลี่ยนเส้นทางบน global.asax ได้ (ฉันไม่ได้คอมเมนต์ซ้ำ)

และไม่น่าเชื่อว่าไม่มีใครพูดถึงเรื่องนี้คุณสามารถโทร:

http://localhost:2316/Inventory/ViewStockNext?firstItem=11

ใน @ Url.Action จะเป็น:

@Url.Action("ViewStockNext", "Inventory", new {firstItem=11});

ขึ้นอยู่กับประเภทของสิ่งที่คุณกำลังทำสุดท้ายจะเหมาะสมกว่า นอกจากนี้คุณไม่ควรดำเนินการ ViewStockNext และแทนที่จะใช้ ViewStock กับดัชนี (2 เซ็นต์ของฉัน)


15

ในการเปลี่ยนคำตอบของ Jarret Meyerคุณต้องเปลี่ยนชื่อพารามิเตอร์เป็น 'id' หรือเพิ่มเส้นทางดังนี้:

routes.MapRoute(
        "ViewStockNext", // Route name
        "Inventory/ViewStockNext/{firstItem}",  // URL with parameters
        new { controller = "Inventory", action = "ViewStockNext" }  // Parameter defaults
    );

เหตุผลคือเส้นทางเริ่มต้นจะค้นหาเฉพาะการดำเนินการที่ไม่มีพารามิเตอร์หรือพารามิเตอร์ที่เรียกว่า 'id'

แก้ไข: เฮ้ไม่เป็นไร Jarret เพิ่มตัวอย่างเส้นทางหลังจากโพสต์


8

หรือทำด้วยคุณสมบัติเส้นทาง:

public class InventoryController : Controller
{
    [Route("whatever/{firstItem}")]
    public ActionResult ViewStockNext(int firstItem)
    {
        int yourNewVariable = firstItem;
        // ...
    }
}

คุณสมบัตินี้อาจใช้ไม่ได้กับ MVC เวอร์ชันเก่า
Suat Atan PhD

นอกจากนี้เพื่อให้ได้ผลคุณต้องแน่ใจว่าคุณได้เรียกใช้routes.MapMvcAttributeRoutes();ภายในRegisterRoutes(RouteCollection)วิธีการของแอปพลิเคชัน(โดยปกติจะนั่งร้านใน App_Start \ RouteConfig.cs) มันอาจไม่อยู่ในนั้นโดยปริยาย
Daniel Scott

7

Headspring สร้างไลบรารีที่ดีที่ช่วยให้คุณสามารถเพิ่มนามแฝงให้กับพารามิเตอร์ของคุณในแอตทริบิวต์ในการดำเนินการ ลักษณะเช่นนี้:

[ParameterAlias("firstItem", "id", Order = 3)]
public ActionResult ViewStockNext(int firstItem)
{
    // Do some stuff
}

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

คุณสามารถหาได้จากNugetและอ่านบทความของ Jeffrey Palermo ได้ที่นี่


7

public ActionResult ViewNextItem(int? id)ทำให้idจำนวนเต็มเป็นประเภทที่ว่างเปล่าไม่จำเป็นต้องมีการแปลงสตริง <-> int


3

การใช้คุณลักษณะ ASP.NET Core Tag Helper:

<a asp-controller="Home" asp-action="SetLanguage" asp-route-yourparam1="@item.Value">@item.Text</a>

แดกดันคำตอบที่สั้นที่สุดคือสิ่งที่ดีที่สุด (อันนี้)

1

มีอีกวิธีหนึ่งที่จะทำให้สำเร็จได้ (อธิบายรายละเอียดเพิ่มเติมในตัวอย่างเพจเจอร์ของ Stephen Walther

โดยพื้นฐานแล้วคุณสร้างลิงก์ในมุมมอง:

Html.ActionLink("Next page", "Index", routeData)

ใน routeData คุณสามารถระบุคู่ชื่อ / ค่า (เช่น routeData ["page"] = 5) และในฟังก์ชันดัชนีควบคุมพารามิเตอร์ที่เกี่ยวข้องจะได้รับค่า นั่นคือ,

public ViewResult Index(int? page)

จะมีการส่งหน้าเป็น 5 ฉันต้องยอมรับว่ามันค่อนข้างผิดปกติที่สตริง ("เพจ") จะกลายเป็นตัวแปรโดยอัตโนมัติ - แต่นั่นเป็นวิธีที่ MVC ทำงานในภาษาอื่นเช่นกัน ...


0

เหตุผลสำหรับการปฏิบัติพิเศษของ "id" คือมีการเพิ่มลงในการแมปเส้นทางเริ่มต้น หากต้องการเปลี่ยนแปลงให้ไปที่ Global.asax.cs และคุณจะพบบรรทัดต่อไปนี้:

routes.MapRoute ("Default", "{controller}/{action}/{id}", 
                 new { controller = "Home", action = "Index", id = "" });

เปลี่ยนเป็น:

routes.MapRoute ("Default", "{controller}/{action}", 
                 new { controller = "Home", action = "Index" });

0

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

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