Dynamicky změně titulu o SiteMapNode

hlasů
4

Máme webové stránky, která používá bažiny standardní výchozí sitemap s bezpečnostní ořezávání takto:

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

Všechno velmi dobře, ale požadavek přišel do změnit Titlez jednoho uzlu na základě některých back-end kritérií. Zní to jako jednoduchá věc, ale zřejmě ne.

Pokus 1 - Manipulace s SiteMapResolveudálost. Nezdá se, že na tom, kde se zachází tato událost, Ukázal jsem ho Global.asaxjen z toho důvodu, že byl jedním z míst, kde jsem to zkusil a fungovalo to.

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

To fungovalo, kdy byla příslušná stránka přešli, ale bohužel součástí navigace webu zahrnuje pole se seznamem, který je dat vázaný na mapu stránek, jako je tento:

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

Je-li toto menu vykreslen se SiteMapResolveneaktivuje událost pro některý z obsahu, protože je aktuální uzel je stránka, na které je definována menu. Jako výsledek, menu zobrazuje název nesmysl zástupný ze souboru fyzického Sitemap spíše než správný titul.

Pokus 2 - psát své vlastní poskytovatele sitemap. Nechtěl jsem duplikovat všechny výchozí chování je, takže jsem pocházet z výchozího poskytovatele následujícím způsobem.

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

To nefunguje, protože GetChildNodesse nezdá být volána velmi často při navigaci po webu.

Pokus o 3 - Pokuste se okamžitě opravit data poté, co se nahraje do paměti, než když je přístupná.

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

Zdá se, že práce. Nicméně, já se bojím o volání GetAllNodesv BuildSiteMapmetodě. Prostě to vypadá špatně se mi rekurzivně vytáhnout všechna data do paměti jen opravit jednu hodnotu. Také nemám žádnou kontrolu nad tím, kdy BuildSiteMapse nazývá. Raději bych něco jako pokus 1, která se nazývá na požádání při prvním požadovaná data uzel.

Pokus o 4 (nový) - Jako Pokus 2, ale převažující všechny virtuální členy, které jsou co do činění s čtení dat ( CurrentNode, FindSiteMapNode, FindSiteMapNodeFromKey, GetChildNodes, GetCurrentNodeAndHintAncestorNodes, GetCurrentNodeAndHintNeighborhoodNodes, GetParentNode, GetParentNodeRelativeToCurrentNodeAndHintDownFromParent, GetParentNodeRelativeToNodeAndHintDownFromParent, HintAncestorNodes, HintNeighborhoodNodes), aby se pokusili zachytit čtení dynamické uzlu někam.

To nefungovalo. Dal jsem příkazy ladění ve všech přepsána členů, a zdá se, že žádná z nich vůbec se nazývají při vázání dat do rozevíracího seznamu. Jediné vysvětlení mě napadá, je, že uzly jsou načteny do paměti najednou v průběhu BuildSiteMaphovoru, takže SiteMapNodenení bít třídy zprostředkovatele při výčtu podřízené uzly.

Má někdo nějaké lepší návrhy?

Položena 26/10/2009 v 13:02
zdroj uživatelem
V jiných jazycích...                            


4 odpovědí

hlasů
2

V naší vlastní SiteMapProvider bychom přepsat BuildSiteMap metody a konstrukci SiteMapNodes ručně. Chcete-li změnit a / nebo přidat vlastní vlastnosti můžeme přidat vlastní atributy k SiteMapNodes prostřednictvím vytvoření NameValueCollection a přidat předat tuto skutečnost SiteMapNode konstruktor.

Odpovězeno 26/10/2009 v 13:51
zdroj uživatelem

hlasů
1

Díky Christian pro svůj výzkum. Pomocí své výsledky, jsem přišel s následující, které by mohly pomoci ostatním:

' Dynamically update some menu items.
'
' Since the correct Medical Center ID is not known until runtime, need to
' append "&MEDICAL_CENTER_ID=xxx" to all of the report's URLs in Web.sitemap.
Public Shared Sub UpdateMenu(ByVal MedicalCenterID As String)
  Dim CurrentNodeTitle As String = ""
  Dim NodeReadOnlyProperty As Boolean

  ' Home menu item
  CurrentNodeTitle = SiteMap.CurrentNode.Title

  ' Determines if the current node has child nodes.
  If (SiteMap.CurrentNode.HasChildNodes) Then
    ' Loop through top level 1 menu items (looking for Reports)
    For Each ChildNodesEnumerator1 As SiteMapNode In SiteMap.CurrentNode.ChildNodes
      CurrentNodeTitle = ChildNodesEnumerator1.Title
      If CurrentNodeTitle = "Reports" Then
        ' Loop through level 2 menu items (looking for specfic reports)
        For Each ChildNodesEnumerator2 As SiteMapNode In ChildNodesEnumerator1.ChildNodes
          CurrentNodeTitle = ChildNodesEnumerator2.Title
          If CurrentNodeTitle = "Multi-Day Vehicle Requests" Or _
           CurrentNodeTitle = "XXXXXXXXXXXXXXXXX" Then
            ' First check if the URL has not been modified already
            If InStr(ChildNodesEnumerator2.Url, "MEDICAL_CENTER_ID") = 0 Then
              NodeReadOnlyProperty = ChildNodesEnumerator2.ReadOnly
              ChildNodesEnumerator2.ReadOnly = False
              ChildNodesEnumerator2.Url = ChildNodesEnumerator2.Url & "&MEDICAL_CENTER_ID=" & MedicalCenterID
              ChildNodesEnumerator2.ReadOnly = NodeReadOnlyProperty
            End If
          End If
        Next
      End If
    Next
  End If
End Sub
Odpovězeno 16/12/2011 v 19:21
zdroj uživatelem

hlasů
1

Díky Markovi a Rex pro návrhy. To, co jsem skončil dělat odcházel poskytovatele sitemap sám a jen upevnění nahoru jeden uzel v hlavní stránce, tedy:

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

    ' Do this as early as possible in the page lifecycle so that it happens before any
    ' automatic data binding or control initialisation is done.
    Dim node As SiteMapNode = GetNodeToEdit()
    Dim nodeReadOnly As Boolean = node.ReadOnly
    node.ReadOnly = False
    node.Title = GetNodeTitle()
    node.ReadOnly = nodeReadOnly

End Sub

Nicméně, jsem přijal odpověď Marka, protože to je to, jak to udělám, pokud se ukáže, že rozsáhlejší změny je třeba udělat v budoucnu.

Odpovězeno 09/11/2009 v 09:56
zdroj uživatelem

hlasů
1

Jsi dost blízko u pokus # 2 - stačí také nutné potlačit GetParentNode a FindSiteMapNode stejně.

Odpovězeno 26/10/2009 v 13:39
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more