문제

우리는 보안 트리밍과 함께 Bog-Standard Default 사이트 맵을 사용하는 웹 사이트가 있습니다.

<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

이것은 작동하는 것 같습니다. 그러나 나는 전화가 걱정됩니다 GetAllNodes 에서 BuildSiteMap 방법. 하나의 값을 고치기 위해 모든 데이터를 메모리로 재귀 적으로 끌어 당기는 것은 잘못된 것 같습니다. 또한, 나는 언제 통제 할 수 없습니다 BuildSiteMap 호출됩니다. 나는 노드 데이터가 처음 필요할 때 요청에 따라 호출되는 시도 1과 비슷한 것을 선호합니다.

시도 4 (신규) - 시도 2와 같지만 우선적입니다 모두 읽기 데이터와 관련된 가상 회원 (CurrentNode, FindSiteMapNode, FindSiteMapNodeFromKey, GetChildNodes, GetCurrentNodeAndHintAncestorNodes, GetCurrentNodeAndHintNeighborhoodNodes, GetParentNode, GetParentNodeRelativeToCurrentNodeAndHintDownFromParent, GetParentNodeRelativeToNodeAndHintDownFromParent, HintAncestorNodes, HintNeighborhoodNodes), 어딘가에 동적 노드의 판독을 가로 채려고 노력하십시오.

이것은 작동하지 않았습니다. 나는 모든 재정의 멤버에게 디버그 진술을했으며, 데이터가 드롭 다운 목록에 바인딩 될 때 전혀 호출되지 않은 것 같습니다. 내가 생각할 수있는 유일한 설명은 노드가 모두 BuildSiteMap 전화를 걸어 SiteMapNode 자식 노드를 열거 할 때 제공자 클래스에 도달하지 않습니다.

누구든지 더 나은 제안이 있습니까?

도움이 되었습니까?

해결책

사용자 정의 SiteMapprovider에서는 BuildSitemap 메소드를 무시하고 SiteMapNodes를 수동으로 구성합니다. 사용자 정의 속성을 변경 및/또는 추가하기 위해 이름 valuecollection을 작성하여 SiteemapNodes에 사용자 정의 속성을 추가하고이를 SetemapNode 생성자에 추가합니다.

다른 팁

당신은 시도 #2와 매우 가깝습니다 - 당신은 또한 또한 무시할 필요가 있습니다. getparentnode 그리고 FindSitemapNode 또한.

제안에 대해 Mark와 Rex에게 감사드립니다. 내가 한 일은 Siteemap 제공 업체를 내버려두고 마스터 페이지의 하나의 노드를 수정하는 것이 었습니다.

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

그러나 나는 Mark의 답변을 받아 들였다. 왜냐하면 앞으로 더 광범위한 수정이 필요하다는 것이 밝혀지면 그렇게 할 것입니다.

당신의 연구에 감사드립니다. 당신의 결과를 사용하여, 나는 다른 사람들을 도울 수있는 다음을 생각해 냈습니다.

' 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
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top