Dynamisches ändern der Titel des SiteMapNode

Haben wir eine website, verwendet eine Moor-standard-Standard-sitemap mit Sicherheit trimmen, wie folgt:

<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>

Alle sehr gut, aber eine Anfrage gekommen, um ändern Sie die Title eines Knotens basierend auf einem back-end-Kriterien. Klingt wie eine einfache Sache, aber anscheinend nicht.

Versuch 1 - Umgang mit der SiteMapResolve Veranstaltung. Es scheint keine Rolle wo dieses Ereignis wird abgewickelt, ich habe gezeigt, dass es in Global.asax bloß weil das war einer der Orte, die ich versuchte es und es funktionierte.

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

Dies funktioniert gut, wenn die entsprechende Seite navigiert wurde, aber leider ist ein Teil der navigation auf der Website beinhaltet ein Kombinationsfeld, das Daten an die Website anzeigen wie diese:

<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" />

Wenn das Menü dargestellt wird, die SiteMapResolve Ereignis nicht Feuer für den Inhalt, da der aktuelle Knoten ist die Seite, auf der das Menü definiert wird. Als ein Ergebnis, das Menü zeigt den Unsinn, den Platzhalter Titel aus der physikalischen XML-sitemap-Datei, anstatt den richtigen Titel.

Versuch 2 - Schreiben meiner eigenen sitemap-provider. Ich wollte nicht zu duplizieren, die Standard-Verhalten, also versuchte ich, die sich aus der Standard-Anbieter wie folgt.

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

Diese funktioniert nicht, da GetChildNodes scheint nicht aufgerufen zu werden, sehr oft beim navigieren rund um die Website.

Versuch 3 - korrigieren Sie die Daten sofort, nachdem es in den Speicher geladen werden, sondern wenn auf Sie zugegriffen wird.

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

Diese scheint zu funktionieren. Allerdings bin ich besorgt über den Aufruf GetAllNodes im BuildSiteMap Methode. Es scheint mir falsch zu sein rekursiv ziehen Sie alle Daten in den Speicher nur zu reparieren, einen Wert. Auch habe ich keine Kontrolle darüber, Wann BuildSiteMap genannt wird. Ich würde lieber etwas mehr wie Versuch 1, dass heißt auf Nachfrage, wenn der Knoten die ersten Daten erforderlich.

Versuch 4 (NEU) - Wie Versuch 2, aber überschreiben alle virtuelle Mitarbeiter, die mit Lesen zu tun Daten (CurrentNode, FindSiteMapNode, FindSiteMapNodeFromKey, GetChildNodes, GetCurrentNodeAndHintAncestorNodes, GetCurrentNodeAndHintNeighborhoodNodes, GetParentNode, GetParentNodeRelativeToCurrentNodeAndHintDownFromParent, GetParentNodeRelativeToNodeAndHintDownFromParent, HintAncestorNodes, HintNeighborhoodNodes), versuchen abzufangen, das Lesen der dynamischen Knoten irgendwo.

Funktionierte dies nicht. Ich legte debug-Anweisungen in alle überschrieben Mitglieder, und es scheint, dass keiner von Ihnen überhaupt genannt werden, wenn Sie Datenbindung, um die dropdown-Liste. Die einzige Erklärung die ich mir denken kann ist, dass die Knoten alle in den Speicher gelesen, in einem Rutsch während der BuildSiteMap nennen, so dass die SiteMapNode ist nicht zu schlagen, die provider-Klasse beim auflisten von untergeordneten Knoten.

Hat jemand besser Vorschläge?

  • Danke für deine ausführliche Frage gestellt. Es half einem ähnlichen Fall, die ich hatte!!!
Schreibe einen Kommentar