【问题标题】:MVCSiteMapProvider some nodes match, others do notMVCSiteMapProvider 一些节点匹配,其他不匹配
【发布时间】:2015-11-23 11:40:40
【问题描述】:

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

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

List 动作是 Home 控制器和区域的默认动作,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 操作为 empty 的 MVC 路由有关。如果我把List的路由改成:

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

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

编辑 - 简化路由

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

【问题讨论】:

    标签: c# .net model-view-controller url-routing mvcsitemapprovider


    【解决方案1】:

    问题 #1:

    MSDN:

    默认路线

    您还可以在控制器级别应用 [Route] 属性,将操作捕获为参数。然后,该路由将应用于控制器中的所有操作,除非在特定操作上定义了特定 [Route],覆盖控制器上的默认设置

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

    问题 #2:

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

    然后我发现脚手架为/Area/&lt;area name&gt;/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 和随附的演示以获得指导。

    【讨论】:

    • 感谢您的帮助。我不明白这如何回答我的问题。如果使用[Route("List/{page?}/{itemsPerPage?}")] 等路由,则[Route("Search/{tags?}/{page?}")] 也可以使用。如果我对列表 [Route("{page?}/{itemsPerPage?}")] 使用空操作,那么它不会。路由参数无效。
    • 使用属性路由时,动作从不为空。它是从action方法派生的。路由[Route("{page?}/{itemsPerPage?}")] 需要丢失 URL 的“动作”部分才能工作,但它仍然使用在路由值字典中声明的动作中的动作名称。此路由将匹配 any 带有 2 个段的 URL,因为占位符可以是任何东西。它是否有效取决于您是否有任何其他路由与在此路由之前注册的 2 个段匹配的 URL - 在 .NET 路由中,第一个匹配总是获胜。
    • 太棒了,这当然是有道理的。我仍然不明白为什么 SiteMapNode 与我的搜索路线不匹配。抱歉这么慢!
    • 见我上面的编辑。在这种情况下,我已经验证了节点匹配,但请确保您在正确的布局页面中声明了 @Html.MvcSiteMap().SiteMapPath()。此外,请参阅this demo 以查看它与这种情况下的节点匹配(但请注意,该演示未解决上述问题 #3)。
    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 2019-01-17
    • 1970-01-01
    • 2018-04-18
    • 2021-06-23
    相关资源
    最近更新 更多