@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,

Другие вопросы по тегам