mvcSitemap 和多条路线
mvcSitemap and multiple routes
我正在尝试使用 MVC 站点地图为我的应用程序创建面包屑路径。我有多个路由到用户控制器,需要为每个路由保留面包屑。 mvcSiteMap如何将每个节点映射到路由?
我有以下进入用户的可能途径:
/User/{action}/{userid}
/User/{groupid}/{action}/{userid}
我分别想要以下面包屑路径:
App Root > Users > {User Name} > {Action}
App Root > Group Management > {Group Name} > {User Name} > {Action}
上面的第一条路线足够直截了当,我用 [SiteMapTitle("Mail")] 修饰了 Details 控制器以显示对象 Mail 属性而不是“Details”,并且编辑用 [SiteMapTitle( "Mail", Target = AttributeTarget.ParentNode)] 编辑时保留邮箱地址。
但是,在使用第二条路线时,我无法弄清楚如何完成所有这些操作。面包屑路径根本不显示任何内容。组部分中的用户部分似乎什么都不做。实现此目标的最佳方法是什么?
Mvc.Sitemap:
<mvcSiteMapNode title="User Management" controller="User" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="Group Management" controller="Group" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="New" action="Create" controller="Group" />
</mvcSiteMapNode>
...
</mvcSiteMapNode>
路线:
routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("ByGroup2", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional, groupid = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("User", "User/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
节点:
<mvcSiteMapNode title="User Management" controller="User" action="Index" route="Default">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="Default" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="Default" preservedRouteParameters="id"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="Group Management" controller="Group" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" route="ByGroup" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="New" action="Create" controller="Group" />
</mvcSiteMapNode>
路线:
routes.MapRoute(
name: "Group",
url: "Group/{action}/{groupid}",
defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });
routes.MapRoute(
name: "ByGroup",
url: "User/{groupid}/{action}/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
constraints: new { groupid = new GuidConstraint() });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
说明
您在 ByGroup2
路线上定义了 2 个可选航段,这是不允许的。可选段必须位于 URL 的最右侧,并且后面不能跟必需的段。这可能会导致问题。
此外,我没有看到 ByGroup2
路线的任何实际用途。
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches User
/User/Index - matches User
我想不出可以匹配 ByGroup2
的情况。但是如果它 确实 匹配,你的参数将被放入不同的路由键,而不是它匹配 User
路由,这可能会造成混淆。
此外,您的 User
路线似乎没有在 Default
路线上添加任何内容。因此,您的路由配置可能看起来像这样并做完全相同的事情(减去路由值位置的混淆,这可能会给您带来问题)。
routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
然后匹配看起来像这样。
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches Default
/User/Index - matches Default
但是,您的 preservedRouteParameters 也有问题。
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
要使 preservedRouteParameters 匹配多个级别,ancestor 节点的所有自定义路由值(在本例中为 id
和 groupid
)必须被提供。此外,它们必须具有相同的含义。为此,id
必须始终通过节点一直引用同一实体,并且必须包含在每个 link 中,无论多深。您必须为群组实体选择与用户实体不同的路由键。
要清除此问题,您可以再更改一次路线以将所有信息放入所需的路线中。您已经完成大部分工作了 - 您只需要修复组节点的 ID。
routes.MapRoute(
name: "Group",
url: "Group/{action}/{groupid}",
defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });
routes.MapRoute(
name: "ByGroup",
url: "User/{groupid}/{action}/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
constraints: new { groupid = new GuidConstraint() });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
和节点:
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" route="ByGroup" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
注意到 /Group/Index
节点下面的每条路由现在都有一个 groupid
,并且 groupid
键总是指同一个实体?
此外,为了确保我们只匹配相关的路由,我们明确指定了它。如果我们不这样做,用户节点将是不明确的,因此您将得到错误的面包屑痕迹(第一个匹配的节点获胜)。
route="ByGroup"
使用上述配置,您需要将 link 构建到 Users
、Users/Details
、Users/Edit
和 Users/Manage
,其中包括当前 groupid
(当然还有当前用户 ID)。
@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid>, groupid = <groupid> }, null)
然后当你导航到"Edit User" link时,groupid将在当前请求中,它将它提供给Users/Details
节点,Group/Edit
节点和 Group/Details
节点解析 URLs 以便您可以通过面包屑路径导航回这些位置。
有关另一个示例,请参阅代码下载中的 Forcing-A-Match-2-Levels 示例 of this article。
没有组的用户部分将匹配 Default
路由,并在构建没有 groupid
的 URL 时显示适当的面包屑痕迹。
所以我们显式指定默认路由:
route="Default"
并像这样构建 URL:
@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid> }, null)
我正在尝试使用 MVC 站点地图为我的应用程序创建面包屑路径。我有多个路由到用户控制器,需要为每个路由保留面包屑。 mvcSiteMap如何将每个节点映射到路由?
我有以下进入用户的可能途径:
/User/{action}/{userid}
/User/{groupid}/{action}/{userid}
我分别想要以下面包屑路径:
App Root > Users > {User Name} > {Action}
App Root > Group Management > {Group Name} > {User Name} > {Action}
上面的第一条路线足够直截了当,我用 [SiteMapTitle("Mail")] 修饰了 Details 控制器以显示对象 Mail 属性而不是“Details”,并且编辑用 [SiteMapTitle( "Mail", Target = AttributeTarget.ParentNode)] 编辑时保留邮箱地址。
但是,在使用第二条路线时,我无法弄清楚如何完成所有这些操作。面包屑路径根本不显示任何内容。组部分中的用户部分似乎什么都不做。实现此目标的最佳方法是什么?
Mvc.Sitemap:
<mvcSiteMapNode title="User Management" controller="User" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="Group Management" controller="Group" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="New" action="Create" controller="Group" />
</mvcSiteMapNode>
...
</mvcSiteMapNode>
路线:
routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("ByGroup2", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional, groupid = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("User", "User/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
节点:
<mvcSiteMapNode title="User Management" controller="User" action="Index" route="Default">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="Default" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="Default" preservedRouteParameters="id"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="Group Management" controller="Group" action="Index">
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" route="ByGroup" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="New" action="Create" controller="Group" />
</mvcSiteMapNode>
路线:
routes.MapRoute(
name: "Group",
url: "Group/{action}/{groupid}",
defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });
routes.MapRoute(
name: "ByGroup",
url: "User/{groupid}/{action}/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
constraints: new { groupid = new GuidConstraint() });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
说明
您在 ByGroup2
路线上定义了 2 个可选航段,这是不允许的。可选段必须位于 URL 的最右侧,并且后面不能跟必需的段。这可能会导致问题。
此外,我没有看到 ByGroup2
路线的任何实际用途。
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches User
/User/Index - matches User
我想不出可以匹配 ByGroup2
的情况。但是如果它 确实 匹配,你的参数将被放入不同的路由键,而不是它匹配 User
路由,这可能会造成混淆。
此外,您的 User
路线似乎没有在 Default
路线上添加任何内容。因此,您的路由配置可能看起来像这样并做完全相同的事情(减去路由值位置的混淆,这可能会给您带来问题)。
routes.MapRoute("ByGroup", "User/{groupid}/{action}/{id}",
new { controller = "User", action = "Index", id = UrlParameter.Optional }, new { groupid = new GuidConstraint() });
routes.MapRoute("Default", "{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
然后匹配看起来像这样。
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Edit/123 - matches ByGroup
/User/131f89da-0dca-40f0-bc99-41559d13fc7f/Index - matches ByGroup
/User/Edit/123 - matches Default
/User/Index - matches Default
但是,您的 preservedRouteParameters 也有问题。
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="id"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
要使 preservedRouteParameters 匹配多个级别,ancestor 节点的所有自定义路由值(在本例中为 id
和 groupid
)必须被提供。此外,它们必须具有相同的含义。为此,id
必须始终通过节点一直引用同一实体,并且必须包含在每个 link 中,无论多深。您必须为群组实体选择与用户实体不同的路由键。
要清除此问题,您可以再更改一次路线以将所有信息放入所需的路线中。您已经完成大部分工作了 - 您只需要修复组节点的 ID。
routes.MapRoute(
name: "Group",
url: "Group/{action}/{groupid}",
defaults: new { controller = "Group", action = "Index", groupid = UrlParameter.Optional });
routes.MapRoute(
name: "ByGroup",
url: "User/{groupid}/{action}/{id}",
defaults: new { controller = "User", action = "Index", id = UrlParameter.Optional },
constraints: new { groupid = new GuidConstraint() });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
和节点:
<mvcSiteMapNode title="Details" action="Details" controller="Group" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="Group" preservedRouteParameters="groupid"/>
<mvcSiteMapNode title="Users" controller="User" action="Index" route="ByGroup" preservedRouteParameters="groupid">
<mvcSiteMapNode title="Details" action="Details" controller="User" route="ByGroup" preservedRouteParameters="id, groupid">
<mvcSiteMapNode title="Edit" action="Edit" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
<mvcSiteMapNode title="Manage" action="Manage" controller="User" route="ByGroup" preservedRouteParameters="id, groupid"/>
</mvcSiteMapNode>
注意到 /Group/Index
节点下面的每条路由现在都有一个 groupid
,并且 groupid
键总是指同一个实体?
此外,为了确保我们只匹配相关的路由,我们明确指定了它。如果我们不这样做,用户节点将是不明确的,因此您将得到错误的面包屑痕迹(第一个匹配的节点获胜)。
route="ByGroup"
使用上述配置,您需要将 link 构建到 Users
、Users/Details
、Users/Edit
和 Users/Manage
,其中包括当前 groupid
(当然还有当前用户 ID)。
@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid>, groupid = <groupid> }, null)
然后当你导航到"Edit User" link时,groupid将在当前请求中,它将它提供给Users/Details
节点,Group/Edit
节点和 Group/Details
节点解析 URLs 以便您可以通过面包屑路径导航回这些位置。
有关另一个示例,请参阅代码下载中的 Forcing-A-Match-2-Levels 示例 of this article。
没有组的用户部分将匹配 Default
路由,并在构建没有 groupid
的 URL 时显示适当的面包屑痕迹。
所以我们显式指定默认路由:
route="Default"
并像这样构建 URL:
@Html.ActionLink("Edit User", "Edit", "User", new { id = <userid> }, null)