更好的 SiteMapResolve






4.83/5 (10投票s)
2006年3月1日
3分钟阅读

90638

884
描述了如何创建一个更有用的 SiteMapResolve 事件。
引言
我最近一直在开发一个 ASP.NET 2.0 网站,并使用新的站点地图功能来实现菜单和面包屑导航功能。 然而,我需要为特定页面动态地修改站点地图结构。
其他尝试过此操作的人可能知道 SiteMap.SiteMapResolve
事件,该事件可用于动态构造站点地图节点。 但是,此事件有一个相当令人恼火的设计缺陷 - 它是 static
。 因此,将事件处理程序附加到它将导致在每个请求上调用该处理程序(实际上,对于访问 SiteMap.CurrentNode
属性的每个请求)。
本文介绍了一个 ASP.NET 2.0 页面的基类,该基类提供特定于页面的 SiteMapResolve
事件。 继承自此基类的页面可以简单地挂钩到此事件,并自由地修改站点地图结构,因为知道这些更改只会影响该页面的当前请求。
使用代码
在你进一步操作之前,运行示例项目并特别注意以下内容
- 诸如“联系我们”和“常见问题解答”之类的页面在站点地图文件中列出。
- NewsItem.aspx 页面未在站点地图文件中列出。 因此,它不会出现在菜单中。 主页上有三个指向新闻项的链接,这是访问 NewsItem.aspx 页面最简单的方法。
- 当您查看新闻项时,会显示一个直观的面包屑导航 - 此面包屑导航是动态构造的站点地图节点的结果。
最重要的类型是 PageBase
类。 此类继承自 System.Web.UI.Page
并添加一个 SiteMapResolve
事件,该事件仅针对该页面触发。 要使用该类,只需声明您的页面继承自它,如下所示
public partial class NewsItem : Support.PageBase
一旦您继承了 PageBase
,您就可以以通常的方式挂钩到 SiteMapResolve
事件
protected override SiteMapNode OnSiteMapResolve(SiteMapResolveEventArgs e)
{
//construct and return your custom SiteMapNode
//here - see download for example code
}
上面,我提到 PageBase.SiteMapResolve
事件仅针对处理它的特定页面触发。 这并不完全准确。 PageBase
类使用一个名为 IsSamePage
的辅助方法来确定是否应触发该事件。 默认情况下,如果请求映射到相同的物理路径并具有相同的查询字符串,则此方法返回 true
。 在大多数情况下,这已经足够了,但在必要时可以重写和自定义该方法。
有趣的是,IsSamePage
的默认实现实际上并没有区分页面的单独实例。 也就是说,如果同时处理对同一页面的多个请求,您最终可能会代表页面的另一个实例处理该事件。 只要您的站点地图结构完全基于从查询字符串中获取的信息,这都无关紧要。 这是因为不同的查询字符串将导致 IsSamePage
返回 false
,因此,该事件不会触发。
如果您的 SiteMapResolve
处理依赖于其他一些信息,请务必相应地覆盖 IsSamePage
。 例如,如果您依赖于会话信息来构造站点地图结构,您可以像这样覆盖 IsSamePage
protected virtual bool IsSamePage(HttpContext context1, HttpContext context2)
{
if (base.IsSamePage(context1, context2))
{
return context1.Session["myKey"] == context2.Session["myKey"];
}
return false;
}
使用此覆盖后,只有在以下情况下才会触发 PageBase.SiteMapResolve
事件
- 该请求用于与当前页面相同的物理文件。
- 该请求具有与当前页面相同的查询字符串。
- 会话中键为 "
myKey
" 的会话值在两个会话中都匹配。
摘要
本文中提供的代码将使您能够更轻松地在 ASP.NET 2.0 页面中构造动态站点地图结构。 随意将 PageBase
代码复制到您自己的项目中,并在必要时对其进行修改。 您的项目中可能已经有一个基页,在这种情况下,您可以简单地将相关代码复制到您的基页中。
历史
- 2006 年 3 月 1 日:首次修订。