在 MvcSiteMapProvider 中为具有动态参数的 DynamicNode 创建子节点

2023-12-20

我正在使用 MvcSiteMapProvider 2.2.1 (http://mvcsitemap.codeplex.com),并且当这些子节点具有动态参数 (id) 时,在动态节点下创建子节点(使用dynamicNodeProvider)时遇到问题。

我正在失去以下路线的面包屑:

商店/5/产品/编辑/23

其中 url 模式为:

商店/{storeID}/{控制器}/{action}/{id}

当省略 ID 时(即“新建”操作),它可以正常工作。但是,当指定 ID 时,它与路线不匹配,并且我的面包屑(使用 SiteMapPath 帮助程序)为空。

我的网站地图:(略)

<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-2.0">
    <mvcSiteMapNode title="Home" controller="Dashboard" action="Index" changeFrequency="Always" updatePriority="Normal">
        <mvcSiteMapNode title="My Account" controller="Account" action="Index" key="Account" />
        <mvcSiteMapNode title="My Stores" area="Stores" controller="Home" action="Index" visibilityProvider="ControlPanel.Areas.Stores.StoreAreaVisibilityProvider, ControlPanel"  >
            <mvcSiteMapNode title="Store" action="Index" dynamicNodeProvider="ControlPanel.Areas.Stores.StoreAreaNodeProvider, ControlPanel" />
        </mvcSiteMapNode>
    </mvcSiteMapNode>
</mvcSiteMap>

地区报名:

public override void RegisterArea(AreaRegistrationContext context)
{
        context.MapRoute(
            "Store_Index",
            "Stores",
            new { action = "Index", controller = "Home" },
            new string[] { "ControlPanel.Areas.Stores.Controllers" }
            );

        context.MapRoute(
            "Store_default",
            "Stores/{storeID}/{controller}/{action}/{id}",
            new { action = "Index", controller = "Manage", id = UrlParameter.Optional },
            new { storeID = @"\d+" },
            new string[] { "ControlPanel.Areas.Stores.Controllers" }
        );
    }

第一次尝试:

我尝试的第一件事是在站点地图 xml 中创建子节点作为动态节点的子节点。这根本不起作用,这些最终都成为“家”的孩子。我会在其中放置一个 ParentKey 属性,但每个商店都会重复这些属性,因此会有多个父键

<?xml version="1.0" encoding="utf-8" ?>
<mvcSiteMap xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-2.0">
  <mvcSiteMapNode title="Home" controller="Dashboard" action="Index" changeFrequency="Always" updatePriority="Normal">
    <mvcSiteMapNode title="My Account" controller="Account" action="Index" key="Account" />
    <mvcSiteMapNode title="My Stores" area="Stores" controller="Home" action="Index" visibilityProvider="ControlPanel.Areas.Stores.StoreAreaVisibilityProvider, ControlPanel"  >
      <mvcSiteMapNode title="Store" action="Index" dynamicNodeProvider="ControlPanel.Areas.Stores.StoreAreaNodeProvider, ControlPanel">
        <mvcSiteMapNode title="Products" area="Stores" controller="Products" action="Index">
          <mvcSiteMapNode title="Edit" area="Stores" controller="Products" action="Edit"/>
          <mvcSiteMapNode title="New" area="Stores" controller="Products" action="Edit"/>
        </mvcSiteMapNode>
      </mvcSiteMapNode>
    </mvcSiteMapNode>
  </mvcSiteMapNode>
</mvcSiteMap>

第二次尝试:

看来下一个选择是在我的 DynamicNodeProvider 中添加子节点。除了具有动态参数的节点之外,这效果更好

(为了便于解释,对以下内容进行了修改...)

public class StoreAreaNodeProvider : IDynamicNodeProvider
{
    public IEnumerable<DynamicNode> GetDynamicNodeCollection()
    {
        var nodes = new List<DynamicNode>();

        foreach (var store in repo.GetStores())
        {
            DynamicNode node = new DynamicNode();
            node.Title = store.Name;
            node.Area = "Stores";
            node.Controller = "Manage";
            node.Action = "Index";
            node.RouteValues.Add("storeID", store.StoreID);
            node.Key = "Store_" + store.StoreID.ToString();

            nodes.Add(node);

            //Child of node
            DynamicNode productsNode = new DynamicNode();
            productsNode.Title = "Products";
            productsNode.Area = "Stores";
            productsNode.Controller = "Products";
            productsNode.Action = "Index";
            productsNode.RouteValues.Add("storeID", store.StoreID);
            productsNode.ParentKey = String.Format("Store_{0}", store.StoreID.ToString());
            productsNode.Key = String.Format("Store_{0}_Products", store.StoreID.ToString());

            nodes.Add(productsNode);

            //child of productsNode
            DynamicNode editNode = new DynamicNode();
            editNode.Title = "Edit";
            editNode.Area = "Stores";
            editNode.Action = "Edit";
            editNode.Controller = "Products";
            editNode.RouteValues.Add("storeID", store.StoreID);
            //I can't add the RouteValue "ID" here because it is dynamic
            //I would have do loop through every product for this store with
            //another dynamic node provider, but that seems terribly inefficient and stupid
            editNode.ParentKey = String.Format("Store_{0}_Products", store.StoreID.ToString());
            editNode.Attributes.Add("visibility", "SiteMapPathHelper,!*");

            nodes.Add(editNode);
        }

        return nodes;
    }
}

总之

是否有效:商店/5/产品/新品
不起作用:商店/5/产品/编辑/23
对于 URL 模式:商店/{storeID}/{控制器}/{action}/{id}

我希望能够做什么:

editNode.Attributes.Add("isDynamic", "true");
editNode.Attributes.Add("dynamicParameters", "id");

如何在作为dynamicNode 的子节点的节点上模仿旧MvcSiteMapProvider 的dynamicParameters 属性?基本上我需要它在匹配路由时忽略“id”路由值。

希望我正确地解释了这一点,并且没有让您不知所措。谢谢!


UPDATE:

这是基于 Jakub 的答案对我有用的解决方案。

在 MvcSiteMapProvider 2.x 中,您可以自行实现 ISiteMapNodeUrlResolver,而不必修改源代码。所以我基本上添加了具有dynamicParameters属性的能力

Class:

namespace ControlPanel
{
    public class CustomSiteMapNodeUrlResolver : ISiteMapNodeUrlResolver
    {
        public virtual string ResolveUrl(MvcSiteMapNode mvcSiteMapNode, string area, string controller, string action, IDictionary<string, object> routeValues)
        {
            RequestContext ctx;
            if (HttpContext.Current.Handler is MvcHandler)
                ctx = ((MvcHandler)HttpContext.Current.Handler).RequestContext;
            else
                ctx = new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData());

            //Begin Added Code
            if (mvcSiteMapNode["dynamicParameters"] != null)
            {
                foreach (var item in mvcSiteMapNode["dynamicParameters"].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var dp = item.Trim();
                    routeValues[da] = ctx.RouteData.Values[dp];
                }
            }
            //End Added Code

            return new UrlHelper(ctx).Action(action, controller, new RouteValueDictionary(routeValues));
        }
    }
}

网页配置:

<siteMap defaultProvider="MvcSiteMapProvider" enabled="true">
  <providers>
    <clear/>
    <add name="MvcSiteMapProvider"
         type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider"
         siteMapFile="~/Mvc.Sitemap"
         securityTrimmingEnabled="true"
         attributesToIgnore="visibility,dynamicParameters"
         scanAssembliesForSiteMapNodes="true" 
         siteMapNodeUrlResolver="ControlPanel.CustomSiteMapNodeUrlResolver, ControlPanel"
         siteMapNodeVisibilityProvider="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider" />
  </providers>
</siteMap>

动态节点提供者:

DynamicNode node = new DynamicNode();
node.Attributes.Add("dynamicParameters", "id");

我使用的是 1.x 版本。 我在动态参数方面也遇到了类似的问题。

我必须修改源代码 - 在 MvcSiteMapNode.cs 中进行更改。这是 Url 属性的新实现

    public override string Url
    {
        get
        {
            if (!string.IsNullOrEmpty(this.url))
                return this.url;

            RequestContext ctx;
            if (HttpContext.Current.Handler is MvcHandler)
                ctx = ((MvcHandler)HttpContext.Current.Handler).RequestContext;
            else
                ctx = new RequestContext(new HttpContextWrapper(HttpContext.Current), new RouteData());

            var routeValues = new RouteValueDictionary(RouteValues);

            foreach (var key in DynamicParameters)
                routeValues.Add(key, ctx.RouteData.Values[key]);

            return new UrlHelper(ctx).Action(Action, Controller, routeValues);
        }
        set
        {
            this.url = value;
        }
    }

请注意dynamicParameters 的实际值是如何添加到routeValues 集合中的。

上述更改允许我在站点地图中定义动态参数(如“id”)并使用 Account/User/Edit/23 等链接创建面包屑。

我简要浏览了 2.x 版本,您应该能够应用类似的补丁。 希望它能帮助你...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 MvcSiteMapProvider 中为具有动态参数的 DynamicNode 创建子节点 的相关文章

  • 有没有任何工具可以查看针对数据库运行的查询?

    是否有任何工具可以检查 asp net 或 sql server 并报告针对数据库运行的所有查询 我问这个问题的原因是我正在一个项目中使用 Linq 并且想要仔细检查它对每个页面实际执行的操作 理想情况下 我想在浏览器中查看页面并获得为创建
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 警告 C4800:“int”:强制值为 bool“true”或“false”(性能警告)

    我的代码中有这个问题 bool CBase isNumber return id MID NUMBER bool CBase isVar return id MID VARIABLE bool CBase isSymbol return i
  • 为什么子函数不销毁GtkWindow?

    这是我的代码 void window first void enter window2 GtkWidget w gpointer data void quit GtkWidget w gpointer data void quit int
  • 将 dataGridView 中选定的行作为对象检索

    我有一堂这样的课 public partial class AdressBokPerson public long Session get set public string F rnamn get set public string Ef
  • opencv中如何去除二值图像噪声?

    将图像转换为二值图像 黑白 后如果有任何噪音怎么办 我消除了那些不需要的噪音 您可以看到下图的黑色区域内有一些白噪声 我该如何去除噪声 使用opencv http img857 imageshack us img857 999 blackn
  • 控制台应用程序中使用 Unicode 字符的 _tprintf

    我正在从 Unicode 构建的控制台应用程序 使用 C 和 Visual Studio 2008 执行这个简单的输出 此代码旨在在 Windows 上运行 tprintf L Some sample string n 一切正常 但是如果我
  • 如何自定义 Google 测试失败消息?

    我编写了一个如下所示的 Google 测试 它将一些计算值与 CSV 文件中预期存储的值进行比较 class SampleTest public testing Test public void setupFile const std st
  • 配置:错误:无法运行C编译的程序

    我正在尝试使用 Debian Wheezy 操作系统在我的 Raspberry Pi 上安装不同的软件 当我运行尝试配置软件时 我尝试安装我得到此输出 checking for C compiler default output file
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • valgrind 在 Raspberry Pi 上返回未处理的指令

    我最近一直在尝试在运行 Debian GNU Linux7 0 喘息 的树莓派 型号 b 上使用 valgrind 来调试分段错误 每次我在编译的 C 程序上运行 valgrind 时 都会得到类似以下内容的信息 disInstr arm
  • Gremlin.net 文本包含等效项

    我正在使用 Gremlin net 库连接到 janus 图形服务器 我使用 cassandra 和弹性搜索进行数据存储和索引 在我使用的 gremlin 语言和 gremlin 控制台中文本包含在属性的文本中进行搜索 我正在使用混合索引
  • Type.GetInterfaces() 仅适用于声明的接口

    首先 像这样的问题有很多 也许有些OP甚至在问同样的问题 问题是这些问题的答案 无论是否接受 都没有真正回答这个问题 至少我找不到 如何确定类直接声明的接口 而不是由父级或声明的接口继承的接口 e g interface I interfa
  • 如何同步nosql db(ravendb)中的更改

    我已经开始在 RavenDB 的示例上学习 NoSQL 我从一个最简单的模型开始 假设我们有由用户创建的主题 public class Topic public string Id get protected set public stri
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 具有四个 && 的 LINQ Where 子句

    我正在尝试在Where 子句中创建一个带有4 个参数的LINQ 查询 这是一个 Windows 8 应用程序项目 我正在使用 SQLite 数据库 SQLite 实现 https github com praeclarum sqlite n
  • 从对列表创建邻接列表类型结构

    在 C 中 我有 class Pair int val1 int val2 我有一个来自以下来源的配对列表 List
  • 如何在 C 中创建最低有效位设置为 1 的掩码

    这个功能如何运作 最低有效 n 位设置为 1 的掩码 Example n 6 gt 0x2F n 17 gt 0x1FFFF 我根本不明白这些 尤其是 n 6 gt 0x2F 另外 什么是面膜 通常的方法是采取1 并将其左移n位 这会给你类
  • 在windows + opengl中选择图形设备

    我知道如何使用 openGL 打开窗口 使用 Win32 或其他工具包 但是当系统有2块显卡时 如何选择要渲染的图形设备 我的编程语言是 C 我专注于 Windows 但任何示例都将受到欢迎 编辑 也许更好地解释我的问题是个好主意 以便添加
  • 将一个 IEnumerable 拆分为多个 IEnumerable

    我是 linq 新手 我需要根据指示器将 Couple string text bool Indicator 类型的 IEnumerable 拆分为多个 IEnumerable 我尝试使用skipWhile 和 TakeWhile 但没有找

随机推荐

  • 需要 ANSI 92 递归 SQL 语句

    我目前正在将 SQL Server SQL 语句转换为其 ANSI 通用等效项 并且一直坚持使用WITH 语句的递归语句 为了集中讨论这个问题 我将问题简化如下 如果我有两张桌子 报告单位 col1 关键 col2 ParentReport
  • 有终结器但没有 IDisposable 的单例

    这是我从 CLR via C Effective C 和其他资源中对 IDisposable 和终结器的理解 IDisposable 用于确定性地清理托管和非托管资源 负责非托管资源 例如文件句柄 的类应该实现 IDisposable 并提
  • 在视图下方显示 toast 小部件

    对于那些之前在这个项目上帮助过我的人 非常感谢 我的代码不再有任何问题 并且我做了额外的调整 现在该应用程序实际上已经很强大了 我还想做一件事 请参阅屏幕截图layout https i stack imgur com NJW9Y jpg
  • 从 Windows C 函数返回字符串

    我对 C 和 C 中的纯 Windows API 级函数完全是新手 最近一直在尝试 NET 互操作性 我已经构建了一个简单的库 它已成功地将数值 int float 等 返回给 NET 调用者 但我在字符串方面没有那么幸运 我尝试了各种不同
  • jQuery Mobile 重用标题和导航

    我是 jQuery Mobile 的新手 在理解重用标题和常规导航时遇到问题 所以我创建了一个标题 其右侧有一个菜单按钮 单击此菜单栏时 会出现一个弹出窗口 其中包含其他页面的链接 div h1 Home h1 a href popupMe
  • 使用带有 '\xae' 的元素转义列表并打印结果

    我有一个清单L u steve u micheal u pedro xae 当我尝试阅读它时 出现错误 我相信它与 xae 有关 gt gt gt L u steve u micheal u pedro xae gt gt gt gt gt
  • 从java voip开始[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我必须编写一个聊天应用程序 能够使用
  • 无法 npm 安装 canvas [Windows 上的 NodeJs]?

    我正在尝试使用 ag psd 包来操作 psd 文件 它仅适用于结构 但如果您也想读取图像数据 则会遇到错误 错误如下 Cannot find module canvas code MODULE NOT FOUND 但如果我尝试安装画布 我
  • 每个派生表必须有自己的别名 - 来自组合降序 MySQL 的错误

    我想通过来自两个不同列的两个 strtotime 时间戳对一个 mysql 表进行排序 我有以下 mysql 命令 SELECT FROM SELECT 1 AS table vid req timestamp AS timestamp t
  • 失败 [INSTALL_FAILED_INVALID_APK]

    当我单击运行刚刚在 Android Studio 0 2 10 中创建的项目并选择我的 Android 通过 USB 连接并通过 USB 进行调试 时 出现以下错误 Waiting for device Target device 0123
  • Twilio 未通过 AWS Lambda 实时发送 WhatsApp 消息

    很抱歉这篇文章很长 但这只是为了更好地解释 因为英语不是我的母语 我正在使用 API Gateway Lambda 通过 POST 请求发送 WhatsApp 消息 我遇到过这种奇怪的行为 看起来 Twilio 需要在 2 个请求或一段时间
  • 如何为 flutter 中的资产创建 APK 扩展文件

    我创建了一个 flutter 应用程序 其中包含大小约为 450mb 的视频资源 我已经在Apple应用商店中成功发布了该应用程序 但 Google Play 不接受我的 APK 因为它超过了 200mb 的限制 我尝试采用创建 APK 扩
  • 在 Visual Studio 2015 中使用 Protractor 测试 ASP.NET Core 应用程序

    我有一个基于核心模板包中的 angular2 模板的 ASP NET Core 项目 我添加了第二个使用 xunit 和量角器进行项目 http dotnetthoughts net end to end testing angularjs
  • 为什么自定义并发队列上的dispatch_sync会死锁

    在自定义并发dispatch queue上使用dispatch sync时 我发现我的应用程序出现间歇性死锁 我正在使用类似于中描述的方法迈克 阿什的博客 http www mikeash com pyblog friday qa 2011
  • Curl 7.43.0 不会在 MSVC 2013 中构建

    在 Visual Studio 2013 中从 cUrl 7 43 0 构建 libcurl w ssl 时 编译器报告以下错误 1 gt 构建开始 项目 libcurl 配置 DLL 调试 DLL OpenSSL DLL LibSSH2
  • 我如何滥用空合并运算符?这是否正确评估“null”?

    我试图在 Unity 的 C 脚本中使用空合并运算符 我的项目脚本运行时设置为 NET 4 x 因此它应该可以正常工作 问题在于 即使 LEFT 操作数的计算结果为 null 它也无法正确返回 RIGHT 操作数 这是一个示例声明不起作用当
  • Terraform:在另一个资源中引用在 for_each 中创建的资源

    当我有一个托管区域时 我可以轻松创建该区域 然后通过按名称引用托管区域 在委托账户中为该区域创建 NS 记录 编辑为了避免混淆 这是我想要实现的目标 但对于多个托管区域并且域的所有者是管理帐户 https dev to arswaw cre
  • 网站移动兼容性

    如何制作既兼容桌面浏览器又兼容移动浏览器的网站 针对桌面和移动设备的替代 CSS 文件有一个技巧 在 HTML header 中实现如下
  • Pygame:为什么我无法绘制圆形精灵

    我创建了以下代码 但不知道为什么无法创建圆形精灵 我真的在网上到处找 发现了同样的事情 但当我尝试它时 它不起作用 我想我只需要在更新和其他代码行之间切换 我是 pygame 的新手 所以请非常明确 谢谢 这是主要功能 import pyg
  • 在 MvcSiteMapProvider 中为具有动态参数的 DynamicNode 创建子节点

    我正在使用 MvcSiteMapProvider 2 2 1 http mvcsitemap codeplex com 并且当这些子节点具有动态参数 id 时 在动态节点下创建子节点 使用dynamicNodeProvider 时遇到问题