controle ASP.Net TreeView na página mestra nem sempre é preenchida
-
22-07-2019 - |
Pergunta
Eu estou trabalhando em meu primeiro projeto ASP.Net, e eu parecem ter sido jogado no fundo do poço imediatamente. Todos os meus arquivos do site são armazenados em um banco de dados, então eu estou usando um VirtualPathProvider para acessá-los. Essa parte funciona bem, mas então eu precisava de um mapa do site que dinamicamente pegar todos os arquivos desde que o usuário irá adicionar / apagar arquivos como eles vão. Para fazer isso, eu criei uma classe que herda StaticSiteMapProvider, criou um SiteMapDataSource na minha página mestra, e uma TreeView para usá-lo. Para a maior parte, isso funciona. Quando você carregar a página que você vê o TreeView e contém todos os nós que é suposto. No entanto, de vez em quando o TreeView é completamente em branco - nenhum nó em tudo. Eu até copiou o TreeView em uma página de conteúdo. O TreeView página de conteúdo sempre funciona, mesmo quando o MasterPage não. (Também eu não sabia um controle em uma página de conteúdo poderia usar uma fonte de dados em uma página mestre até que eu esqueci de copiar a fonte de dados!)
Tentando depurar isso, eu coloquei uma exceção de jogar na minha função BuildSiteMap () no SiteMapProvider só para provar a mim mesmo que o código foi realmente executado. O que descobri foi que a exceção foi atingido cada vez. No entanto, o rastreamento de pilha não era o mesmo de cada vez.
Na maioria das vezes, isso é o que eu tenho:
[Exception: Test] ADEM.clsSiteMap.BuildSiteMap() in c:\inetpub\wwwroot\App_Code\clsSiteMap.vb:49 System.Web.StaticSiteMapProvider.GetChildNodes(SiteMapNode node) +54 System.Web.SiteMapNode.get_ChildNodes() +27 System.Web.UI.WebControls.SiteMapDataSource.GetNodes(SiteMapNode node) +52 System.Web.UI.WebControls.SiteMapDataSource.GetNodes() +329 System.Web.UI.WebControls.SiteMapDataSource.GetTreeView(String viewPath) +35 System.Web.UI.WebControls.SiteMapDataSource.GetHierarchialView(String viewPath) +32 System.Web.UI.HierarchialDataSourceControl.System.Web.UI.IHierarchialDataSource.GetHierarchialView(String viewPath) +10 System.Web.UI.WebControls.HierarchialDataBoundControl.GetData(String viewPath) +25 System.Web.UI.WebControls.TreeView.DataBindNode(TreeNode node) +73 System.Web.UI.WebControls.TreeView.PerformDataBinding() +120 System.Web.UI.WebControls.HierarchicalDataBoundControl.PerformSelect() +85 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 System.Web.UI.WebControls.TreeView.DataBind() +4 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82 System.Web.UI.WebControls.BaseDataBoundControl.OnPreRender(EventArgs e) +22 System.Web.UI.WebControls.TreeView.OnPreRender(EventArgs e) +36 System.Web.UI.Control.PreRenderRecursiveInternal() +80 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842
No entanto, quase tão frequentemente como o TreeView viria para cima em branco, eu tenho esse:
[Exception: Test] ADEM.clsSiteMap.BuildSiteMap() in c:\inetpub\wwwroot\App_Code\clsSiteMap.vb:49 System.Web.StaticSiteMapProvider.FindSiteMapNode(String rawUrl) +133 System.Web.SiteMapProvider.FindSiteMapNode(HttpContext context) +54 System.Web.SiteMapProvider.get_CurrentNode() +35 System.Web.UI.WebControls.TreeView.DataBindNode(TreeNode node) +219 System.Web.UI.WebControls.TreeView.PerformDataBinding() +120 System.Web.UI.WebControls.HierarchicalDataBoundControl.PerformSelect() +85 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 System.Web.UI.WebControls.TreeView.DataBind() +4 System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82 System.Web.UI.WebControls.BaseDataBoundControl.OnPreRender(EventArgs e) +22 System.Web.UI.WebControls.TreeView.OnPreRender(EventArgs e) +36 System.Web.UI.Control.PreRenderRecursiveInternal() +80 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Control.PreRenderRecursiveInternal() +171 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842
Eu acho que o pouco útil de código seria a função BuildSiteMap:
Public Overrides Function BuildSiteMap() As System.Web.SiteMapNode
Dim node As SiteMapNode = Nothing
SyncLock Me
node = TryCast(HttpRuntime.Cache("SiteMap"), SiteMapNode)
If node Is Nothing Then
MyBase.Clear()
Throw New Exception("Test")
node = New SiteMapNode(Me, "FO1", "default.cnt", "Home")
AddNode(node)
siteRoot = node
AddFolders(node)
AddFiles(node)
HttpRuntime.Cache.Insert("SiteMap", node, New SiteMapCacheDependency())
End If
Return node
End SyncLock
End Function
AddFolders () e AddFiles () apenas fazer mais do mesmo, então por razões de brevidade Vou deixá-los a menos que alguém pensa que eles são importantes.
Eu tentei postar o código para o treeview aqui, mas parece que o site realmente não gosto disso. Posso dizer que eu estou definindo a propriedade DataSourceID em vez de atribuí-la em tempo de execução. Eu tentei-o em ambos os sentidos, não parece fazer a diferença.
Eu não sou realmente certo o que mais pode ser útil, por isso, deixe-me saber se você precisar de mais detalhes.
Agora estou deixado querer saber se este poderia ser um indício para o meu problema ou se é apenas uma coincidência. Se é uma pista, eu sou demasiado denso para descobrir isso. Algum deste faz sentido para alguém?
Solução
Como se vê, o problema estava em um pouco de código que eu não acho que foi pena postagem. Parece que todos os exemplos que eu encontrei faz algo parecido com isto:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
Return siteRoot
End Function
Acontece que GetRootNodeCore () seja chamado praticamente fora direita do portão, por isso às vezes SiteRoot não é nada. Portanto, a solução é a seguinte:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
If siteRoot Is Nothing Then
SyncLock Me
BuildSiteMap()
End SyncLock
End If
Return siteRoot
End Function
Eu não vou tomar o crédito para descobrir que no meu próprio, alguém apontou para mim aqui: http://forums.asp.net/p/1473236/3420805.aspx#3420805