Routing: Die aktuelle Handlungsanforderung […] ist zwischen den folgenden Aktionsmethoden nicht eindeutig

100

Ich habe eine Ansicht namens Browse.chtml, in der der Benutzer einen Suchbegriff eingeben oder den Suchbegriff leer lassen kann. Wenn ich den Suchbegriff eingebe, möchte ich die Seite anleiten, http://localhost:62019/Gallery/Browse/{Searchterm} und wenn nichts eingegeben wird, möchte ich den Browser anleiten http://localhost:62019/Gallery/Browse/Start/Here.

Wenn ich das versuche, erhalte ich die Fehlermeldung:

Die aktuelle Anforderung für die Aktion 'Durchsuchen' für den Controllertyp 'GalleryController' ist zwischen den folgenden Aktionsmethoden nicht eindeutig: System.Web.Mvc.ActionResult Browse (System.String) für den Typ AutoApp_MVC.Controllers.GalleryController System.Web.Mvc.ActionResult Browse (Int32, System.String) für den Typ AutoApp_MVC.Controllers.GalleryController

Alles, was ich mit MVC mache, ist zum ersten Mal. Ich bin mir nicht sicher, was ich sonst noch versuchen soll.

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);
}

Ich habe dies auch in 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
         });
Dave
quelle

Antworten:

161

Sie können maximal 2 Aktionsmethoden mit demselben Namen auf einem Controller haben, und dazu muss 1 [HttpPost]und die andere sein [HttpGet].

Da beide Methoden GET sind, sollten Sie entweder eine der Aktionsmethoden umbenennen oder auf einen anderen Controller verschieben.

Obwohl Ihre 2 Browse-Methoden gültige C # -Überladungen sind, kann der MVC-Aktionsmethoden-Selektor nicht herausfinden, welche Methode aufgerufen werden soll. Es wird versucht, eine Route mit der Methode abzugleichen (oder umgekehrt), und dieser Algorithmus ist nicht stark typisiert.

Sie können das erreichen, was Sie möchten, indem Sie benutzerdefinierte Routen verwenden, die auf verschiedene Aktionsmethoden verweisen:

... in 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
     });

... und in der Steuerung ...

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);
}

Möglicherweise können Sie auch die gleichnamigen Aktionsmethoden im Controller beibehalten , indem Sie ein [ActionName]Attribut auf eines anwenden , um es zu unterscheiden. Wenn Sie dieselbe Global.asax wie oben verwenden, sieht Ihr Controller dann folgendermaßen aus:

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);
}
danludwig
quelle
Also muss ich in Ihrem obigen Beispiel eine neue Ansicht erstellen? Es sieht so aus, als würde es nicht helfen, das ActionName-Tag zu verwenden, da ich denke, dass dies nur funktioniert, um alle Aktionsmethoden umzubenennen (nicht in der Lage, beide gleichzeitig zu behalten). Es ist gut zu wissen, wie MVC funktioniert. Vielen Dank.
Dave
6
Nein, Sie müssen keine neuen Ansichten erstellen. Sie können immer noch dieselbe Ansicht für beide Aktionen wiederverwenden. return View("Browse", summaries);
Übergeben Sie
Wird eine Überladung in einer zukünftigen Version enthalten sein? Das Ändern von Routen ist zusätzliche Arbeit und zusätzliche Wartung ist erforderlich, wenn Änderungen vorgenommen werden.
Old Geezer
@OldGeezer wahrscheinlich nicht, da es eine Problemumgehung gibt (oben) und weil überladene Aktionsmethoden in einem Controller im Allgemeinen keine gute Idee sind.
Danludwig
4

Ich weiß nicht, wann die Frage gestellt wurde, diese Lösung war verfügbar, aber Sie können verwenden:

Request.QueryString["key"]

Das sollte also für Ihr Problem gut funktionieren:

[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);
} 
Saygın Doğu
quelle
2

Fügen Sie folgenden Code in RouteConfig.cs vor Standardroute

routes.MapMvcAttributeRoutes();

Fügen Sie dem Controller Routenattribute wie folgt hinzu:

    [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>");

    }
omar mohameed
quelle
1

Ich denke, der Punkt ist, dass Sie nicht implizit mit der Anforderungsklasse auf Querystring-Parameter testen müssen.

MVC übernimmt das Mapping für Sie (es sei denn, Sie haben schwerwiegende Änderungen an Ihren MVC-Routen vorgenommen).

Somit ist ein Actionlink-Pfad von

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

würde Ihrem (Oberflächen-) Controller automatisch mit dem definierten Parameter zur Verfügung stehen:

public ActionResult Logout(string DestinationUrl)

MVC erledigt die Arbeit.

Darren Street
quelle