@Html.MvcSiteMap(). Исключение SiteMapPath(): "Неоднозначный контроллер. Найдено несколько типов контроллеров
Я использую @Html.MvcSiteMap().SiteMapPath()
построить след панировочных сухарей.
У меня есть два контроллера, один из них DealsController, который унаследован от класса DealsContorllerBase. Оба класса имеют свои собственные методы Index(), где дочерний метод Index() переопределяет Index() родительского класса. В моей Mvc.sitemap:
<mvcSiteMapNode title="Deals" controller="Deals" action="Index" >
<mvcSiteMapNode title="Deal" controller="Deals" action="ShowSpecificDeal" />
</mvcSiteMapNode>
В функции RegisterRoute:
...
routes.MapRoute(
"Deals", // Route name
"Deals", // URL with parameters
new { controller = "Deals", action = "Index" }, // Parameter defaults
new[] { "InvestX.UI.Web", "InvestX.UI.Controllers" } // namespaces
);
...
DealsController, определенный внутри проекта "InvestX.UI.Web", и DealsControllerBase, определенный внутри проекта "InvestX.UI.Controllers".
Целое исключение как это:
Неоднозначный контроллер. Найдено несколько типов контроллеров для 'DealsController'. Типы, которые соответствуют:
InvestX.UI.Web.Controllers.DealsController InvestX.UI.Controllers.DealsControllerBase`1
Попробуйте сузить места для поиска, добавив пространства имен вашего контроллера в ControllerBuilder.Current.DefaultNamespaces или исключив пространства имен, добавив их в параметр areaNamespacesToIgnore объекта ControllerTypeResolverFactory.
Я знаю, если бы DealsController не был унаследован от DealsControllerBase и просто использовать DealsController, все было бы хорошо. Исключение было вызвано тем, какое действие Index() выполнить: DealsController's или DealsControllerBase. Мой вопрос, как mvcSiteMapNode обрабатывает иерархию родительского / дочернего контроллера, как это?
1 ответ
Опция 1
Я знаю, если бы DealsController не был унаследован от DealsControllerBase и просто использовать DealsController, все было бы хорошо.
Правильный. И это ваш лучший вариант, если время, затрачиваемое на его исправление, не является чрезмерным. Нет веских причин для использования базового контроллера в MVC. Именно так все и должно было быть сделано в ASP.NET, но наследование MVC больше не является лучшим вариантом для сквозных задач. Вы можете выполнить все, что вам нужно, с помощью других расширений фреймворка (особенно глобальных фильтров).
Вариант № 2
Сделайте свой базовый класс абстрактным - ControllerTypeResolver
отфильтровывает абстрактные классы, так как они не могут использоваться MVC как контроллеры напрямую. Маловероятно, что ваш контроллер базового класса должен быть создан в любом случае напрямую.
public abstract class DealsControllerBase : Controller
{
...
}
Вариант № 3
Как указано в сообщении об ошибке, добавьте пространство имен базового контроллера в AreaNamespacesToIgnore
,
Внутренний DI
<add key="MvcSiteMapProvider_ControllerTypeResolverAreaNamespacesToIgnore" value="InvestX.UI.Controllers"/>
Внешний DI
Приведенный пример - другие контейнеры DI похожи.
this.Kernel.Bind<IControllerTypeResolverFactory>().To<ControllerTypeResolverFactory>()
.WithConstructorArgument("areaNamespacesToIgnore", new string[] { "InvestX.UI.Controllers" });
Вариант № 4
Как указано в сообщении об ошибке, вы также можете явно добавить все пространства имен вашего контроллера в ControllerBuilder.Current.DefaultNamespaces
,
ControllerBuilder.Current.DefaultNamespaces.Clear();
ControllerBuilder.Current.DefaultNamespaces.Add("InvestX.UI.Web.Controllers");
ControllerBuilder.Current.DefaultNamespaces.Add("SomeOtherNamespace.Controllers");
Обратите внимание, что это работает только в том случае, если вы не регистрируете пространства имен в своих маршрутах.
Вариант № 5
Я не рекомендую это, но вы также можете избежать этой проблемы, удалив слово Controller
от твоего DealsControllerBase
имя класса Например, назовите это DealsCtrlBase
,