I'm using @Html.MvcSiteMap().SiteMapPath() to build breadcrumbs trail.
I have two controllers, one is DealsController which inherited from class of DealsContorllerBase. The both classes has their own Index() methods, where child's Index() overrides Index() of parent class. In my Mvc.sitemap:
<mvcSiteMapNode title="Deals" controller="Deals" action="Index" >
<mvcSiteMapNode title="Deal" controller="Deals" action="ShowSpecificDeal" />
</mvcSiteMapNode>
In RegisterRoute function:
...
routes.MapRoute(
"Deals", // Route name
"Deals", // URL with parameters
new { controller = "Deals", action = "Index" }, // Parameter defaults
new[] { "InvestX.UI.Web", "InvestX.UI.Controllers" } // namespaces
);
...
The DealsController defined inside "InvestX.UI.Web" project and DealsControllerBase defined inside of "InvestX.UI.Controllers" project.
The whole exception as this:
Ambiguous controller. Found multiple controller types for 'DealsController'. The types that matched are:
InvestX.UI.Web.Controllers.DealsController InvestX.UI.Controllers.DealsControllerBase`1
Consider narrowing the places to search by adding your controller namespaces to ControllerBuilder.Current.DefaultNamespaces or exluding namespaces by adding them to the areaNamespacesToIgnore parameter of ControllerTypeResolverFactory.
I know if the DealsController were not inherited from DealsControllerBase and just use DealsController, everything would be fine. The exception was caused by which Index() action to take: DealsController's or DealsControllerBase's. My question is how does mvcSiteMapNode handle parent/child controller hierarky like this?
Option #1
Correct. And this is your best option provided the time involved in fixing it is not prohibitive. There are no good reasons for using a base controller in MVC. This is the way things had to be done in ASP.NET, but with MVC inheritance is no longer the best option for cross-cutting concerns. You can accomplish everything you need with other extensions to the framework (especially global filters).
Option #2
Make your base class abstract - the
ControllerTypeResolverfilters abstract classes out, since they cannot be used as controllers directly by MVC. It is unlikely that your base class controller needs to be instantiated directly anyway.Option #3
As pointed out in the error message, add your base controller namespace to
AreaNamespacesToIgnore.Internal DI
External DI
Ninject example shown - other DI containers are similar.
Option #4
As pointed out in the error message, you can also add all of your controller namespaces explicitly to the
ControllerBuilder.Current.DefaultNamespaces.Note that this only works if you don't register any namespaces in your routes.
Option #5
I don't recommend this, but you could also avoid this problem by removing the word
Controllerfrom yourDealsControllerBaseclass name. For example, name itDealsCtrlBase.