MVCSiteMapProvider 一些节点匹配,其他不匹配

MVCSiteMapProvider some nodes match, others do not

我正在使用 MvcSiteMapProvider 生成面包屑,但我无法将节点与新功能匹配。我们使用 MVC5 区域并使用最新的 MvcSiteMapProvider.MVC5 库。我们将 i18nResx 文件一起使用,我们的 title 属性是键。我们的页面 URL 在发布后不会更改,因此请使用标准 XML 配置。

我们使用基于 MVC5 属性的路由。

List 动作是家庭控制器和区域的默认动作,Store/ 路线也是如此。效果很好,匹配成功。

Search 操作 Store/Search 路由 匹配节点。

配置

<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0"
    xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0 MvcSiteMapSchema.xsd">

  <mvcSiteMapNode controller="Dashboard" action="Index" title="Foobar" key="Bar">

    <!-- quite a large file -->

    <mvcSiteMapNode area="Store" controller="Home" action="List" title="SiteMap_DocumentStore_Home_List" preservedRouteParameters="page, itemsPerPage, msg">
      <mvcSiteMapNode area="Store" controller="Home" action="Search" title="SiteMap_DocumentStore_Search" preservedRouteParameters="tags, page"/>

      <!-- snip extra entries -->
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMap>

感谢我可以从 ListmvcSiteMapNode 个子项中删除属性 areacontroller。为了完整起见,我将它们留在这里。

家庭控制器

[RouteArea("Store")]
[Route("{action=list}")]
public class HomeController : Controller
{
  [Route("{page?}/{itemsPerPage?}")]
  public ActionResult List(int page = 1, int itemsPerPage = -1, string msg = "")
  {}

  [Route("Search/{tags?}/{page?}")]
    public ActionResult Search(string tags = "", int page = 1)
  {}
}

调查

我感觉这与 List 操作的 MVC 路由 有关。如果我将 List 的路线更改为:

[Route("List/{page?}/{itemsPerPage?}")]
public ActionResult List(int page = 1, int itemsPerPage = -1, string msg = "")
{}

然后搜索节点将匹配,它的兄弟节点(我剪掉的)也会匹配

编辑 - 简化路由

我已经删除了控制器的默认路由 [Route("{action=list}")]。问题依然存在。

问题 #1:

根据 MSDN:

Default Route

You can also apply the [Route] attribute on the controller level, capturing the action as a parameter. That route would then be applied on all actions in the controller, unless a specific [Route] has been defined on a specific action, overriding the default set on the controller.

在你的情况下,默认的控制器级路由将被完全忽略,因为在每种情况下你都有一个覆盖它的操作级路由。

问题 #2:

我通过在 VS 2015 中启动一个新的 MVC 5 项目并添加一个区域和其余配置来研究它“不匹配”的原因。有一段时间我很困惑为什么它不起作用。

然后我发现脚手架为 /Area/<area name>/Views/_ViewStart.cshtml 中的每个区域连接了不同的布局页面。

@{
    Layout = "~/Areas/Store/Views/Shared/_Layout.cshtml";
}

我将其更改为使用共享 ViewStart.cshtml 文件,然后它显示了面包屑路径。

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

问题 #3:

另外,您保存的路由参数有问题。由于它们始终派生自当前请求,因此内部请求必须始终提供其祖先的所有参数。此外,参数在父项和子项之间不得具有不同的含义,因此例如 page 必须针对 ListSearch 引用同一页面。换句话说,每个键名在其祖先中必须是唯一的。

如果它们相同,您只需将附加参数添加到搜索即可解决此问题 URL。

[Route("Search/{page?}/{itemsPerPage?}/{tags?}")]

否则你应该给每个 page 参数一个不同的名称。

请参阅 How to make MvcSiteMapProvider Remember a User's Position 和随附的演示以获取指导。