【发布时间】:2009-10-26 12:02:20
【问题描述】:
我们有一个网站使用沼泽标准默认站点地图和安全调整,如下所示:
<siteMap defaultProvider="default" enabled="true">
<providers>
<add siteMapFile="~/Web.sitemap" securityTrimmingEnabled="true" name="default" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</siteMap>
一切都很好,但是收到了一个请求,要求根据一些后端标准更改一个节点的Title。听起来很简单,但显然不是。
尝试 1 - 处理 SiteMapResolve 事件。 在哪里处理这个事件似乎并不重要,我已经在Global.asax 中展示了它,仅仅是因为那是我尝试过的地方之一并且它有效。
Public Class Global_asax
Inherits System.Web.HttpApplication
Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
AddHandler SiteMap.SiteMapResolve, AddressOf SiteMapResolve
End Sub
Sub Application_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
RemoveHandler SiteMap.SiteMapResolve, AddressOf SiteMapResolve
End Sub
Private Shared Function SiteMapResolve(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
Dim node As SiteMapNode = SiteMap.CurrentNode
If IsThisTheNodeToChange(node) Then
node = node.Clone()
node.Title = GetNodeTitle()
End If
Return node
End Function
End Class
当导航到相关页面时,这工作正常,但不幸的是,站点导航的一部分涉及一个组合框,该组合框与站点地图数据绑定,如下所示:
<asp:SiteMapDataSource ID="siteMapDataSource" runat="Server" ShowStartingNode="false" StartFromCurrentNode="false" StartingNodeOffset="1" />
<asp:DropDownList ID="pageMenu" runat="Server" AutoPostBack="True" DataSourceID="siteMapDataSource" DataTextField="Title" DataValueField="Url" />
呈现此菜单时,不会为任何内容触发SiteMapResolve 事件,因为当前节点是定义菜单的页面。结果,菜单显示物理站点地图文件中的无意义占位符标题,而不是正确的标题。
尝试 2 - 编写我自己的站点地图提供程序。我不想复制所有默认行为,所以我尝试从默认提供程序派生如下。
Public Class DynamicXmlSiteMapProvider
Inherits XmlSiteMapProvider
Private _dataFixedUp As Boolean = False
Public Overrides Function GetChildNodes(ByVal node As SiteMapNode) As SiteMapNodeCollection
Dim result As SiteMapNodeCollection = MyBase.GetChildNodes(node)
If Not _dataFixedUp Then
For Each childNode As SiteMapNode In result
FixUpNode(childNode)
Next
End If
Return result
End Function
Private Sub FixUpNode(ByVal node As SiteMapNode)
If IsThisTheNodeToChange(node) Then
node.ReadOnly = False
node.Title = GetNodeTitle()
node.ReadOnly = True
_dataFixedUp = True
End If
End Sub
End Class
这不起作用,因为在浏览网站时,GetChildNodes 似乎并不经常被调用。
尝试 3 - 尝试在数据加载到内存后立即修复数据,而不是在访问时修复。
Public Class DynamicXmlSiteMapProvider
Inherits XmlSiteMapProvider
Private _dataFixInProgress As Boolean = False
Private _dataFixDone As Boolean = False
Public Overrides Function BuildSiteMap() As SiteMapNode
Dim result As SiteMapNode = MyBase.BuildSiteMap()
If Not _dataFixInProgress AndAlso Not _dataFixDone Then
_dataFixInProgress = True
For Each childNode As SiteMapNode In result.GetAllNodes()
FixUpNode(childNode)
Next
_dataFixInProgress = False
_dataFixDone = True
End If
Return result
End Function
Private Sub FixUpNode(ByVal node As SiteMapNode)
If IsThisTheNodeToChange(node) Then
node.ReadOnly = False
node.Title = GetNodeTitle()
node.ReadOnly = True
End If
End Sub
End Class
这似乎有效。但是,我担心BuildSiteMap 方法中对GetAllNodes 的调用。递归地将所有数据拉入内存以修复一个值对我来说似乎是错误的。此外,我无法控制何时调用 BuildSiteMap。我更喜欢尝试 1 的东西,它在第一次需要节点数据时按需调用。
尝试 4(新) - 类似于尝试 2,但覆盖与读取数据有关的 所有 虚拟成员(CurrentNode、FindSiteMapNode、@987654336 @、GetChildNodes、GetCurrentNodeAndHintAncestorNodes、GetCurrentNodeAndHintNeighborhoodNodes、GetParentNode、GetParentNodeRelativeToCurrentNodeAndHintDownFromParent、GetParentNodeRelativeToNodeAndHintDownFromParent、HintAncestorNodes、HintNeighborhoodNodes),尝试在某处截取动态节点的读取。
这不起作用。我将调试语句放在所有被覆盖的成员中,当数据绑定到下拉列表时,似乎根本没有调用它们。我能想到的唯一解释是,在BuildSiteMap调用期间,所有节点都被一次性读入内存,因此SiteMapNode在枚举子节点时不会碰到提供程序类。
谁有更好的建议?
【问题讨论】:
-
感谢您的详细提问。它帮助了我遇到的类似案例!
标签: .net asp.net vb.net sitemap sitemapprovider