【问题标题】:mvcsitemapprovider breadcrumb breaks after new parameters in URLmvcsitemapprovider 面包屑在 URL 中的新参数后中断
【发布时间】:2015-02-27 20:26:47
【问题描述】:

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

这给面包屑带来了问题。如果我的 URL 是 http://localhost/User/ManageUsers,它会在面包屑中显示“Home > Manage Users > Users”。但是,如果 URL 随页面(即 http://localhost/User/ManageUsers/?page=1)而更改,则面包屑会更改为父级,即“Home > Manage Users”,其中 Manage Users 没有超链接。

我的站点地图设计如下:

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

我发现如果我以某种方式从 URL 中的最后一个删除“/”,面包屑可以正常工作,例如

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

请帮我找到合乎逻辑的解决方案。

【问题讨论】:

  • 请发布您的路由配置。
  • routes.MapRoute( name: "DefaultwithType", url: "{controller}/{action}/{id}/{type}", 默认值: new { controller = "Home", action = “索引”,id = UrlParameter.Optional,类型 = UrlParameter.Optional }); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );

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


【解决方案1】:

我无法解释(或重现)您在斜杠后面看到的行为,但我确实看到了一个潜在问题。

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

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

在这两种情况下,它们都将匹配 URL /User/ManageUsers。这是因为preservedRouteParameters 只在有参数要保留时才起作用,所以它就像一个可选值。

解决此问题的最简单方法是重命名其中一个操作方法。通常,这些是 2 个不同的功能部分(名为 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">

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

// 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 段 URL,否则 DefaultwithType 路由将不匹配 - 如果您的应用程序中有 4 个段的 URL,您可能需要一些固定段或约束,您不打算调用最后一个段 {type} .

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

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

【讨论】:

  • 这里是 routeConfigs: routes.MapRoute( name: "DefaultwithType", url: "{controller}/{action}/{id}/{type}", defaults: new { controller = " Home", action = "Index", id = UrlParameter.Optional, type = UrlParameter.Optional } ); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
  • 我按照您的建议更新到 v4.6.18 并添加了 presevedRouteParameters="page" 但没有任何改变。
  • 我想保持模棱两可,所以当用户点击主链接时,他们会直接移动到可以找到子链接的子页面。不想为 Manage_users 添加 routeMap,因为在这种情况下会添加很多映射,因为页面参数将是很多不同的页面
  • 如果我从“默认”路由中删除 id = UrlParameter.Optional,我会收到不允许目录浏览的错误。但我按照您的指示更改了“DefaultwithType”路线。但结果完全一样没有变化。 URL 仍然有 userdetail/?page=2 并且面包屑仍然无法显示当前页面,而是像以前一样显示父 ID。
  • @sarojanand - 我重读了你的问题并意识到我无法从中推断出确切的问题。我假设您的“管理用户”节点用于用户列表(可以分页),而“用户”节点用于查看特定用户。这是配置它的标准方式,它适用于这种配置。但是,由于您已经描述了行为是什么,但没有描述预期的行为是什么,所以我只是在猜测这一点。哪个节点与预期的页码匹配?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多