【问题标题】:@Html.MvcSiteMap().SiteMapPath() exception: "Ambiguous controller. Found multiple controller types@Html.MvcSiteMap().SiteMapPath() 异常:“不明确的控制器。发现多个控制器类型
【发布时间】:2016-07-05 05:00:07
【问题描述】:

我正在使用@Html.MvcSiteMap().SiteMapPath() 构建面包屑路径。

我有两个控制器,一个是从 DealsContorllerBase 类继承的 DealsController。 这两个类都有自己的 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
        );

...

在“InvestX.UI.Web”项目中定义的 DealsController 和在“InvestX.UI.Controllers”项目中定义的 DealsControllerBase。

整个异常如下:

模棱两可的控制器。找到多种控制器类型 '交易控制器'。匹配的类型有:

InvestX.UI.Web.Controllers.DealsController InvestX.UI.Controllers.DealsControllerBase`1

考虑通过添加控制器来缩小搜索范围 命名空间到 ControllerBuilder.Current.DefaultNamespaces 或 通过将命名空间添加到 areaNamespacesToIgnore 来排除命名空间 ControllerTypeResolverFactory的参数。

我知道如果 DealsController 不是从 DealsControllerBase 继承而只使用 DealsController,一切都会好起来的。 异常是由要采取的 Index() 操作引起的:DealsController 的或 DealsControllerBase 的。 我的问题是 mvcSiteMapNode 如何处理这样的父/子控制器层次结构?

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-5 mvcsitemapprovider asp.net-mvc-sitemap


    【解决方案1】:

    选项#1

    我知道如果 DealsController 不是从 DealsControllerBase 继承而只使用 DealsController,一切都会好起来的。

    正确。这是您最好的选择,前提是修复它所涉及的时间并不令人望而却步。有no good reasons for using a base controller in MVC。这是在 ASP.NET 中必须完成的事情的方式,但使用 MVC 继承不再是 cross-cutting concerns 的最佳选择。您可以使用框架的其他扩展来完成您需要的一切(尤其是global filters)。

    选项 #2

    让你的基类抽象——ControllerTypeResolver filters abstract classes out,因为它们不能被 MVC 直接用作控制器。无论如何,您的基类控制器不太可能需要直接实例化。

    public abstract class DealsControllerBase : Controller
    {
        ...
    }
    

    选项#3

    正如错误消息中指出的,将您的基本控制器命名空间添加到AreaNamespacesToIgnore

    内部 DI

    <add key="MvcSiteMapProvider_ControllerTypeResolverAreaNamespacesToIgnore" value="InvestX.UI.Controllers"/>
    

    外部 DI

    显示的 Ninject 示例 - 其他 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

    我不建议这样做,但您也可以通过从 DealsControllerBase 类名中删除单词 Controller 来避免此问题。例如,将其命名为DealsCtrlBase

    【讨论】:

    • 嗨 NightOwl888,非常感谢您的及时回复和有用的选择。我发现选项 #2 是我的最佳选择,并且非常适合我。我只需要在 DealsController 类中添加覆盖方法,在其中添加设置 node.titile 等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    相关资源
    最近更新 更多