Asp.net mvc 4 MVC站点地图-当不同节点指向同一操作站点地图时。CurrentNode未映射到正确的路由 设置:
我正在使用ASP.NETMVC4和mvcSiteMapProvider来管理我的菜单 我有一个自定义菜单生成器,用于评估节点是否位于当前分支上(即,如果Asp.net mvc 4 MVC站点地图-当不同节点指向同一操作站点地图时。CurrentNode未映射到正确的路由 设置:,asp.net-mvc-4,mvcsitemapprovider,Asp.net Mvc 4,Mvcsitemapprovider,我正在使用ASP.NETMVC4和mvcSiteMapProvider来管理我的菜单 我有一个自定义菜单生成器,用于评估节点是否位于当前分支上(即,如果SiteMap.CurrentNode是CurrentNode或CurrentNode嵌套在其下)。代码包含在下面,但本质上检查每个节点的url,并通过currentnodes“家族树”将其与currentnode的url进行比较 我的自定义菜单生成器使用CurrentBranch添加一个类,该类高亮显示CurrentBranch上的菜单项 问题
SiteMap.CurrentNode
是CurrentNode或CurrentNode嵌套在其下)。代码包含在下面,但本质上检查每个节点的url,并通过currentnodes“家族树”将其与currentnode的url进行比较
我的自定义菜单生成器使用CurrentBranch添加一个类,该类高亮显示CurrentBranch上的菜单项
问题是:
我的自定义菜单工作正常,但我发现mvcsitemprovider
似乎没有以一致的方式评估CurrentNode
的url
:
当两个节点指向同一个操作且仅通过该操作的一个参数进行区分时,SiteMap.CurrentNode似乎没有使用正确的路由(它忽略区分参数并默认为映射到节点中定义的操作的第一个路由)。
问题的例子:
在一个应用程序中,我有成员
成员的MemberStatus
字段可以是“未处理”、“活动”或“非活动”。要更改MemberStatus,我在名为Admin的区域中有一个ProcessMemberController
。使用ProcessMemberController
上的Process
操作完成处理
我的mvcSiteMap有两个节点,它们都映射到进程
操作。它们之间唯一的区别是alternate
参数(这是我客户机的域语义),在一种情况下,该参数的值为“已处理”,而在另一种情况下,该参数的值为“未处理”:
节点:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
工作原理:
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
在这两种情况下,输出都是正确的,正如我所期望的那样
什么不起作用:
假设我的请求涉及第二个选项,即,/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"
例如,对于/Admin/Members/Status/Change/47的请求url,SiteMap.CurrentNode.url
的计算结果为/Admin/Unprocessed/Process/47
。也就是说,它忽略了alternate
参数并使用了错误的路由
CurrentBranch静态属性:
//
///只读。获取包含SiteMap.CurrentNode的站点地图的分支
///
公共静态列表分支
{
得到
{
List currentBranch=null;
如果(currentBranch==null)
{
SiteMapNode cn=SiteMap.CurrentNode;
SiteMapNode n=cn;
List ln=新列表();
如果(cn!=null)
{
while(n!=null&&n.Url!=SiteMap.RootNode.Url)
{
//我不需要检查n.ParentNode==null
//因为cn!=null&&n!=SiteMap.RootNode
ln.添加(n);
n=n.ParentNode;
}
//while循环不包括根节点,因此将其添加到此处
//我可以添加n,现在应该等于SiteMap.RootNode,但这更清楚
ln.Add(SiteMap.RootNode);
//节点是按从CurrentNode开始的相反顺序添加的,因此请将其反转。
ln.Reverse();
}
currentBranch=ln;
}
回流支路;
}
}
问题是:
我做错了什么
这些路由按照我的预期由Html.ActionLlink进行解释,但不是按照我的预期由SiteMap.CurrentNode进行评估。换句话说,在评估我的路线时,SiteMap.CurrentNode会忽略可区分的备用参数。我认为这是因为您试图从参数中获取路线。基本上,MVC只是试图猜测您所指的路线
正确的方法是按名称处理路由。因此,站点地图应该引用路由名称,而不是控制器、操作等。为了以防万一,您可以尝试以下操作:
context.MapRoute(
"Process_New_Members",
"Admin/{alternate}/Process/{MemberId}",
new { controller = "ProcessMembers",
action = "Process",
alternate="Unprocessed",
MemberId = UrlParameter.Optional }
);
这样,您就可以通过需要这个附加参数来区分每条路线。附录-我已经让它工作了!!:
大绊脚石:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
当使用不同的路由指向同一控制器动作时,一个控制器有不同的节点,我遇到的最大问题如下:
您必须给不同的节点一个密钥!!!否则站点地图将无法渲染强>
例如,仅路由属性本身是不够的,您必须为指向同一操作的每个节点指定一个唯一的键,以区分它们:
<mvcSiteMapNode title="Edit Staff" area="Admin" controller="EditStaff" route="Admin_AdministratorDetails" action="Start" key="administrators_details" />
<mvcSiteMapNode title="Edit Staff" area="Admin" controller="EditStaff" route="Admin_StaffDetails" action="Start" key="staff_details" />
在路由注册文件中,您现在可以编写调用相同操作的路由:
context.MapRoute(
"Unprocessed_Details",
"Unprocessed/Edit/{idSolicitor}/{action}",
new { action = "Start", controller = "EditSolicitor", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Inactive_Details",
"Inactive/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Active_Details",
"Solicitors/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
如您所见,这与三条路由调用的操作完全相同。只要我在MVCSitemPanode中指定路由名称,在构建菜单时,路由就会正确区分,并且高亮显示会根据需要工作
关于被XML弄糊涂的注意事项:
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" />
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" />
我深恶痛绝XML。这让我感到困惑和困惑,尤其是当我感冒的时候
问题在于,将route属性添加到MVCSitemPaNodes会增加混淆的可能性
我被弄糊涂了
我最初试过卡洛斯的建议,但没有成功。不确定是什么错误,
@Html.RouteLink("Details", "Active_Details", new { action="Start", controller="EditSolicitor", idSolicitor = item.SolicitorId, returnUrl = Request.RawUrl })
context.MapRoute(
"Unprocessed_Details",
"Unprocessed/Edit/{idSolicitor}/{action}",
new { action = "Start", controller = "EditSolicitor", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Inactive_Details",
"Inactive/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
context.MapRoute(
"Active_Details",
"Solicitors/Edit/{idSolicitor}/{action}",
new { controller = "EditSolicitor", action = "Start", idSolicitor = UrlParameter.Optional }
);
<mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" aurl="/Admin/ProcessMembers/Process/Unprocessed"/>
<mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" url="/Admin/ProcessMembers/Process/Processed" />