我有这个站点地图:
<mvcSiteMapNode title="Projects" controller="Projects" action="Index" key="Home" visibility="!*">
<mvcSiteMapNode title="Projects" controller="Projects" action="Index">
<mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="id">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" preservedRouteParameters="id">
<mvcSiteMapNode title="Edit Session" controller="Sessions" action="Edit" preservedRouteParameters="id"/>
</mvcSiteMapNode>
</mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="My Account" controller="Account" action="ChangePassword" />
<mvcSiteMapNode title="Admin" controller="Admin" action="Index" >
<mvcSiteMapNode title="Create User" controller="Admin" action="AddUser" />
<mvcSiteMapNode title="Manage Users" controller="Admin" action="Users" />
</mvcSiteMapNode>
当我转到会话详细信息页面时,面包屑显示:
Projects > Project > Session
然而,项目链接(转到“项目详细信息”页面)使用与会话相同的ID,而不是它来自的项目。
我尝试将inheritedRouteParameters="id"
添加到“会话详细信息”页面,但它没有改变任何内容。
修改 我添加了不同的savedRouteParameters,但现在“Project”链接回/ Projects / Details而没有附加id。
答案 0 :(得分:3)
savedRouteParameters总是复制当前请求的值,它不会假设“id”是什么。因此,如果在同时显示的2个节点上的savedRouteParameters中使用“id”,则需要确保它们具有相同的含义。
解决此问题的一种方法是为每种情况使用不同的密钥名称(例如,“projectId”和“sessionId”)。然后,您可以在子节点上保留它们,以便“记住”它所属的父节点。
<mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="projectId">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" preservedRouteParameters="projectId,sessionId">
您可能需要修改路由以使其生成符合您要求的URL,但为此,父ID必须是子节点的路由(通常是URL)的一部分。以下是与上述节点配置匹配的示例。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "SessionRoute",
url: "Project/{projectId}/{sessionId}",
defaults: new { controller = "Sessions", action = "Details" });
routes.MapRoute(
name: "ProjectRoute",
url: "Project/{projectId}",
defaults: new { controller = "Projects", action = "Details" });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
查看MvcSiteMapProvider-Forcing-A-Match-2-Levels项目in this demo,看看究竟如何做到这一点。请注意,添加路由是可选的 - 如果您不介意URL中的查询字符串参数,则可以始终使用默认路由。
如果这不适合您,则可以在一个节点参数上使用savedRouteParmeters组合,并明确设置另一个参数。
<mvcSiteMapNode title="Project" controller="Projects" action="Details" preservedRouteParameters="projectId">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="1" preservedRouteParameters="projectId">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="2" preservedRouteParameters="projectId">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="3" preservedRouteParameters="projectId">
或者您可以为您拥有的每个“id”组合创建一个节点。
<mvcSiteMapNode title="Project" controller="Projects" action="Details" id="1">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="1">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="2">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="3">
</mvcSiteMapNode>
<mvcSiteMapNode title="Project" controller="Projects" action="Details" id="2">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="4">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="5">
<mvcSiteMapNode title="Session" controller="Sessions" action="Details" id="6">
</mvcSiteMapNode>
对于最后两个选项,通常最好使用DynamicNodeProvider填充动态数据,而不是用XML标记它们。
这些方法可以创建更干净的URL,但也会消耗更多的RAM。通常对于管理页面,最好使用稍微粗略的URL(savedRouteParmaters)并使用动态节点(和RAM)保存需要搜索引擎索引的页面。
inheritedRouteParameters仅用于从XML配置中的父节点继承值,并且在请求级别无效。
BTW - 您必须确保每个节点上都有唯一的路由值组合。在您的示例中,前2个节点具有完全相同的路由值,这意味着第二个节点永远不会匹配,因为第一个匹配总是获胜。