mvcsitemapprovider breadcrumb在URL中的新参数后中断

时间:2015-02-27 20:26:47

标签: c# asp.net-mvc breadcrumbs mvcsitemapprovider

在我的MVC应用程序中,我们有大约200多页我们正在使用网格。最近我们添加了history.js与网格集成,增加了" page"网址中的参数,如http://localhost/User/ManageUsers/?page=1

这会给面包屑带来问题。如果我的网址为http://localhost/User/ManageUsers,则会显示" 主页>管理用户>用户"在面包屑。但是,如果使用页面http://localhost/User/ManageUsers/?page=1更改网址,则面包屑会更改为父级,即" 主页>管理用户"管理用户没有超链接。

我的站点地图的设计如下:

  <mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers">
    <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" preservedRouteParameters="id">
      <mvcSiteMapNode title="Facilities" controller="User" action="ManageUserFacilities" preservedRouteParameters="id,conf"/>
      <mvcSiteMapNode title="Conversations" controller="User" action="UserConversations" preservedRouteParameters="id,conf"/>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="User Postings" controller="User" action="ManageUserPostings"/>
  </mvcSiteMapNode>

我发现如果我以某种方式删除&#34; /&#34;从URL中的最后一个,面包屑工作正常,例如。

   http://localhost/User/ManageUsers?page=1 //shows correct breadcrumbs
   http://localhost/User/ManageUsers/?page=1 //shows parent node in breadcrumbs

请帮我找到合适的解决方案。

1 个答案:

答案 0 :(得分:0)

我无法解释(或重现)您使用尾部斜杠看到的行为,但我确实看到了潜在的问题。

当涉及将节点与传入路由匹配时,以下2个节点是不明确的:

<mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers">
  <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" preservedRouteParameters="id">

在这两种情况下,它们都会匹配网址/User/ManageUsers。这是因为savedRouteParameters仅在有保留参数时才起作用,因此它就像一个可选值。

解决此问题的最简单方法是重命名其中一个操作方法。通常,这些是两个不同的功能部件(名为IndexDetails),并通过将关注点放入不同的操作方法来应用关注点分离是一件好事。

或者,您可以为第一个节点定义单独的路由,然后显式调出该路由。

routes.MapRoute(
    name: "User_MangageUsers",
    url: "User/ManageUsers",
    defaults: new { controller = "User", action = "ManageUsers" }
);      

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

你的节点:

<mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers" route="User_MangageUsers">
  <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" preservedRouteParameters="id">

这确实无法解决page参数的问题。但是你不应该有一个,因为默认情况下会忽略查询字符串值。我怀疑您的路由配置存在问题,但由于您没有发布,我无法确切地告诉您它是什么。

v4.6.10中添加了一项功能,允许您使用查询字符串参数作为路由匹配的一部分,并且有一项增强功能可以使查询字符串键在v4.6.18中不区分大小写。

如果您使用的是低于v4.6.10的版本,则应升级。如果您至少使用v4.6.10,则可以通过将page参数添加为保留路由参数来解决此问题。

<mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers" route="User_MangageUsers" preservedRouteParameters="page">
  <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" preservedRouteParameters="id">

根据您的路线更新

我仍然无法重现这个问题。

但是,您的路由配置确实存在问题 - 即,在单个路由上指定2个可选参数无效。这可能与您的尾部斜杠问题有关,因为当您关闭两个可选参数时,结果将在生成URL时包含额外的尾部斜杠。使用当前路由配置,Default路由是无法访问的执行路径。

您可以通过更改路由来解决此问题。

routes.MapRoute(
    name: "DefaultwithType",
    url: "{controller}/{action}/{id}/{type}",
    defaults: new { type = UrlParameter.Optional }); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}", 
    defaults: new { controller = "Home", action = "Index" });

现在:

/User/ManageUsers/1/SomeType - matches DefaultwithType
/User/ManageUsers/1          - matches DefaultwithType
/User/ManageUsers            - matches Default
/User                        - matches Default (with action "Index")
/                            - matches Default (with controller "Home", action "Index")

使用此路由配置,您可以通过显式指定路由来消除节点之间的歧义。这可能是必要的,也可能不是必需的 - 首先尝试修复节点,然后再修复此节点。

<mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers" route="Default">
  <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" route="DefaultwithType" preservedRouteParameters="id">

更新以使网格在“用户”节点上工作

// Route to force match with "Users" node
routes.MapRoute(
    name: "User",
    url: "User/ManageUsers/{id}",
    defaults: new { controller = "User", action = "ManageUsers" }); 

routes.MapRoute(
    name: "DefaultwithType",
    url: "{controller}/{action}/{id}/{type}"); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });

节点:

<mvcSiteMapNode title="Manage Users" controller="User" action="ManageUsers" route="Default">
  <mvcSiteMapNode title="Users" controller="User" action="ManageUsers" route="User" preservedRouteParameters="id,page">

现在User路线优先于Default路线。除非提供了4段网址,否则DefaultwithType路由将不匹配 - 如果您的应用中有4个您不打算调用最后一个段的网址,则可能需要一些固定的细分或约束{1}}。

我还在savedRouteParameters中包含了“page”。这可能不是必需的,但如果包含它,它应匹配页码是否在请求中。

“MvcSiteMapProvider_AttributesToIgnore”用于在节点上创建未包含在路由匹配中的自定义属性。它与忽略传入URL中的值无关。