Search code examples
c#asp.net-mvcroutesattributerouting

Multiple controller types were found that match the URL in mvc app


I have a weird bug using attribute routing with the following two controllers:

[Route("{action=Index}")]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }
}

[RoutePrefix("search")]
[Route("{action=Index}")]
public class SearchController : Controller
{
    public ActionResult Index(string searchTerm)
    {
        return View();
    }
}

And in the route config:

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();

As you can see, the second controller should have a prefix of search

However if I go to dev.local/search?searchterm=test

I get the error

The request has found the following matching controller types: Marshalls.WebComponents.Web.Controllers.SearchController Marshalls.WebComponents.Web.Controllers.HomeController

If I remove the [Route("{action=Index}")] from the homecontroller, it will work fine, but then I cannot get to the homepage using http://dev.local/

This hasn't happened before and usually works ok so I'm wondering if anyone can spot anything obvious I have messed up


Solution

  • Add RoutePrefix for HomeController and move Route from controller to methods/actions.

    Empty string in Route and RoutePrefix attributes means that this controller or action is default.

    http://dev.local/ => HomeController and Index action

    http://dev.local/search?searchTerm=123 => SearchController and Index action

    Please keep in mind that only one controller can have empty RoutePrefix and only one action in controller can have empty Route

    [RoutePrefix("")]
    public class HomeController : Controller
    {
        [Route("")]
        public ActionResult Index()
        {
            return View();
        }
    }
    
    [RoutePrefix("search")]
    public class SearchController : Controller
    {
        [Route("")]
        public ActionResult Index(string searchTerm)
        {
            return View();
        }
    }