การกำหนดเส้นทาง: คำขอปัจจุบันสำหรับการดำเนินการ […] มีความคลุมเครือระหว่างวิธีการดำเนินการต่อไปนี้


100

ฉันมีการเรียกดูBrowse.chtmlซึ่งผู้ใช้สามารถป้อนคำค้นหาหรือเว้นว่างไว้ เมื่อป้อนคำค้นหาที่ผมต้องการที่จะตรงหน้าเพื่อและเมื่อไม่มีอะไรจะเข้ามาผมต้องการที่จะตรงเบราว์เซอร์http://localhost:62019/Gallery/Browse/{Searchterm} http://localhost:62019/Gallery/Browse/Start/Here

เมื่อฉันลองสิ่งนี้ฉันได้รับข้อผิดพลาด:

คำขอปัจจุบันสำหรับการดำเนินการ 'เรียกดู' บนตัวควบคุมชนิด 'GalleryController' ไม่ชัดเจนระหว่างวิธีการดำเนินการต่อไปนี้: System.Web.Mvc.ActionResult เรียกดู (System.String) ในประเภท AutoApp_MVC.Controllers.GalleryController System.Web.Mvc.ActionResult เรียกดู (Int32, System.String) บนประเภท AutoApp_MVC.Controllers.GalleryController

ทุกสิ่งที่ฉันทำกับ MVC เป็นครั้งแรก ฉันไม่แน่ใจว่าจะลองทำอะไรอีกในตอนนี้

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

public ActionResult Browse(string name1, string name2)
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

ฉันมีสิ่งนี้ใน Global.asax.cs:

    routes.MapRoute(
         "StartBrowse",
         "Gallery/Browse/{s1}/{s2}",
         new
         {
             controller = "Gallery",
             action = "Browse",
             s1 = UrlParameter.Optional,
             s2 = UrlParameter.Optional
         });



    routes.MapRoute(
         "ActualBrowse",
         "Gallery/Browse/{searchterm}",
         new
         {
             controller = "Gallery",
             action = "Browse",
             searchterm=UrlParameter.Optional
         });

คำตอบ:


161

คุณสามารถมีได้สูงสุด 2 วิธีการดำเนินการที่มีชื่อเดียวกันกับตัวควบคุมและเพื่อที่จะทำเช่นนั้นจะต้องเป็น 1 [HttpPost]และอื่น ๆ [HttpGet]ที่จะต้อง

เนื่องจากทั้งสองวิธีของคุณเป็น GET คุณควรเปลี่ยนชื่อวิธีการดำเนินการวิธีใดวิธีหนึ่งหรือย้ายไปยังตัวควบคุมอื่น

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

คุณสามารถทำสิ่งที่ต้องการให้สำเร็จได้โดยใช้เส้นทางที่กำหนดเองซึ่งชี้ไปที่วิธีการดำเนินการต่างๆ:

... ใน Global.asax

routes.MapRoute( // this route must be declared first, before the one below it
     "StartBrowse",
     "Gallery/Browse/Start/Here",
     new
     {
         controller = "Gallery",
         action = "StartBrowse",
     });

routes.MapRoute(
     "ActualBrowse",
     "Gallery/Browse/{searchterm}",
     new
     {
         controller = "Gallery",
         action = "Browse",
         searchterm = UrlParameter.Optional
     });

... และในตัวควบคุม ...

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

public ActionResult StartBrowse()
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

คุณอาจสามารถใช้วิธีการดำเนินการที่มีชื่อเหมือนกันในคอนโทรลเลอร์ได้โดยใช้[ActionName]แอตทริบิวต์หนึ่งเพื่อแยกความแตกต่าง ใช้ Global.asax เดียวกันกับข้างบนคอนโทรลเลอร์ของคุณจะมีลักษณะดังนี้:

public ActionResult Browse(string id)
{
    var summaries = /* search using id as search term */
    return View(summaries);
}

[ActionName("StartBrowse")]
public ActionResult Browse()
{
    var summaries = /* default list when nothing entered */
    return View(summaries);
}

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

6
ไม่คุณไม่จำเป็นต้องสร้างมุมมองใหม่ ๆ คุณยังสามารถใช้มุมมองเดิมซ้ำสำหรับทั้งสองการกระทำได้ เพียงส่งชื่อมุมมองเป็นอาร์กิวเมนต์แรกไปที่return View("Browse", summaries);
danludwig

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

@OldGeezer อาจไม่ใช่เนื่องจากมีวิธีแก้ปัญหา (ด้านบน) และเนื่องจากวิธีการดำเนินการที่มากเกินไปในคอนโทรลเลอร์โดยทั่วไปไม่ใช่ความคิดที่ดี
danludwig

4

ฉันไม่รู้ว่าเมื่อใดที่มีการถามคำถามวิธีนี้ แต่คุณสามารถใช้:

Request.QueryString["key"]

ดังนั้นสิ่งนี้จะใช้ได้ดีสำหรับปัญหาของคุณ:

[HttpGet]
public ActionResult Browse()
{
    if( Request.QueryString["id"] != null )        
        var summaries = /* search using id as search term */
    else /*assuming you don't have any more option*/
        var summaries = /* default list when nothing entered */

    return View(summaries);
} 

2

เพิ่มรหัสต่อไปนี้ใน RouteConfig.cs ก่อนเส้นทางเริ่มต้น

routes.MapMvcAttributeRoutes();

และเพิ่มคุณลักษณะเส้นทางในตัวควบคุมเช่น:

    [Route("Cars/deteals/{id:int}")]
    public ContentResult deteals(int id)
    {
        return Content("<b>Cars ID Is " + id + "</b>");
    }

    [Route("Cars/deteals/{name}")]
    public  ContentResult deteals(string name)
    {
        return Content("<b>Car name Is " + name + "</b>");

    }

1

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

MVC ทำการแมปให้คุณ (เว้นแต่คุณจะทำการเปลี่ยนแปลงอย่างรุนแรงในเส้นทาง MVC ของคุณ)

ดังนั้นเส้นทาง actionlink ของ

/umbraco/Surface/LoginSurface/Logout?DestinationUrl=/home/

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

public ActionResult Logout(string DestinationUrl)

MVC ทำงาน

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