Dave Dave - 2 months ago 6
C# Question

Routing: The current request for action [...] is ambiguous between the following action methods

I have a View called

Browse.chtml
, where the user can enter a search term, or leave the search term blank. When entering the search term, I want to direct the page to
http://localhost:62019/Gallery/Browse/{Searchterm}
and when nothing is entered, I want to direct the browser to
http://localhost:62019/Gallery/Browse/Start/Here
.

When I try this, I get the error:


The current request for action 'Browse' on controller type 'GalleryController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Browse(System.String) on type AutoApp_MVC.Controllers.GalleryController
System.Web.Mvc.ActionResult Browse(Int32, System.String) on type AutoApp_MVC.Controllers.GalleryController


Everything I'm doing with MVC is for the first time. I'm not sure what else to try at this point.

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


I also have this 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
});

Answer

You can only have a maximum of 2 action methods with the same name on a controller, and in order to do that, 1 must be [HttpPost], and the other must be [HttpGet].

Since both of your methods are GET, you should either rename one of the action methods or move it to a different controller.

Though your 2 Browse methods are valid C# overloads, the MVC action method selector can't figure out which method to invoke. It will try to match a route to the method (or vice versa), and this algoritm is not strongly-typed.

You can accomplish what you want using custom routes pointing to different action methods:

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

... and in the controller...

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

You might also be able to keep the action methods named the same in the controller, by applying an [ActionName] attribute to one to distinguish it. Using the same Global.asax as above, your controller would then look like this:

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