MVC SiteMap - 当不同节点指向同一个动作时,SiteMap.CurrentNode不会映射到正确的路径

awr*_*ley 6 asp.net-mvc-4 mvcsitemapprovider

建立:

我正在使用ASP.NET MVC 4,使用mvcSiteMapProvider来管理我的菜单.

我有一个自定义菜单构建器,用于评估节点是否在当前分支上(即,如果SiteMap.CurrentNode是CurrentNode或CurrentNode是否嵌套在它下面).代码包含在下面,但基本上检查每个节点的url并将其与currentnode的url进行比较,直到currentnodes"family tree".

我的自定义菜单构建器使用CurrentBranch添加一个类,该类突出显示CurrentBranch上的菜单项.

问题:

我的自定义菜单工作正常,但我发现,mvcSiteMapProvider似乎没有评估urlCurrentNode以一致的方式:

当两个节点指向同一个操作并且仅通过操作的参数进行区分时,SiteMap.CurrentNode似乎不使用正确的路径(它忽略区分参数并默认为映射到中定义的操作的第一个路径)节点).

问题示例:

在我的应用程序中Members.

会员的MemberStatus字段可以是"未处理","活动"或"非活动".要更改MemberStatus,我ProcessMemberController在一个名为Admin的区域中有一个.使用上的Process操作完成处理ProcessMemberController.

我的mvcSiteMap有两个节点,它们都映射到Process动作.它们之间的唯一区别是alternate参数(例如我的客户端的域语义),在一种情况下,其值为"已处理",而在另一种情况下为"未处理":

节点:

    <mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
    <mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
Run Code Online (Sandbox Code Playgroud)

路线:

这两个节点的相应路由(同样,区别它们的唯一方法是备用参数的值):

context.MapRoute(
                    "Process_New_Members",
                    "Admin/Unprocessed/Process/{MemberId}",
                    new { controller = "ProcessMembers", 
                        action = "Process", 
                        alternate="Unprocessed", 
                        MemberId = UrlParameter.Optional }
                );


context.MapRoute(
                    "Change_Status_Old_Members",
                    "Admin/Members/Status/Change/{MemberId}",
                    new { controller = "ProcessMembers", 
                        action = "Process", 
                        alternate="Processed", 
                        MemberId = UrlParameter.Optional }
                );
Run Code Online (Sandbox Code Playgroud)

什么有效:

Html.ActionLink助手使用路由并生成我期望的URL:

@Html.ActionLink("Process", MVC.Admin.ProcessMembers.Process(item.MemberId, "Unprocessed")

// Output (alternate="Unprocessed" and item.MemberId = 12):   Admin/Unprocessed/Process/12


@Html.ActionLink("Status", MVC.Admin.ProcessMembers.Process(item.MemberId, "Processed")

// Output (alternate="Processed" and item.MemberId = 23):   Admin/Members/Status/Change/23
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,输出都是正确的,正如我所料.

什么行不通:

假设我的请求涉及第二个选项,即/Admin/Members/Status/Change/47对应于alternate ="Processed"和MemberId为47.

调试我的静态CurrentBranch属性(见下文),我发现SiteMap.CurrentNode显示:

PreviousSibling: null
Provider: {MvcSiteMapProvider.DefaultSiteMapProvider}
ReadOnly: false
ResourceKey: ""
Roles: Count = 0
RootNode: {Home}
Title: "Process"
Url: "/Admin/Unprocessed/Process/47"
Run Code Online (Sandbox Code Playgroud)

即,对于/ Admin/Members/Status/Change/47的请求URL,SiteMap.CurrentNode.Url评估为/Admin/Unprocessed/Process/47.即,它正在忽略alternate参数并使用错误的路径.

CurrentBranch静态属性:

/// <summary>
        /// ReadOnly. Gets the Branch of the Site Map that holds the SiteMap.CurrentNode
        /// </summary>
        public static List<SiteMapNode> CurrentBranch
        {
            get
            {
                List<SiteMapNode> currentBranch = null;
                if (currentBranch == null)
                {
                    SiteMapNode cn = SiteMap.CurrentNode;
                    SiteMapNode n = cn;
                    List<SiteMapNode> ln = new List<SiteMapNode>();
                    if (cn != null)
                    {
                        while (n != null && n.Url != SiteMap.RootNode.Url)
                        {
                            // I don't need to check for n.ParentNode == null
                            // because cn != null && n != SiteMap.RootNode
                            ln.Add(n);
                            n = n.ParentNode;
                        }
                        // the while loop excludes the root node, so add it here
                        // I could add n, that should now be equal to SiteMap.RootNode, but this is clearer
                        ln.Add(SiteMap.RootNode);

                        // The nodes were added in reverse order, from the CurrentNode up, so reverse them.
                        ln.Reverse();
                    }
                    currentBranch = ln;
                }
                return currentBranch;
            }
        }
Run Code Online (Sandbox Code Playgroud)

问题:

我究竟做错了什么?

正如我所期望的那样,路由由Html.ActionLlink解释,但不会像我期望的那样被SiteMap.CurrentNode评估.换句话说,在评估我的路由时,SiteMap.CurrentNode忽略区分备用参数.

Car*_*z T 3

我认为这是因为您试图从参数中获取路线。基本上,MVC 只是试图猜测您可能指的是哪条路线。

正确的方法是按名称处理路由。因此站点地图应该引用路线名称而不是控制器、操作等。