El control ASP.Net TreeView en MasterPage no siempre se llena
-
22-07-2019 - |
Pregunta
Estoy trabajando en mi primer proyecto ASP.Net, y parece que me arrojaron al fondo de inmediato. Todos los archivos de mi sitio se almacenan en una base de datos, por lo que estoy usando un VirtualPathProvider para acceder a ellos. Esa parte funciona bien, pero luego necesitaba un mapa del sitio que recogiera dinámicamente todos los archivos ya que el usuario agregará / eliminará archivos a medida que avanzan. Para hacer eso, creé una clase que hereda StaticSiteMapProvider, creé un SiteMapDataSource en mi página maestra y un TreeView para usarlo. En su mayor parte, esto funciona. Cuando carga la página, ve el TreeView y contiene todos los nodos que se supone que debe. Sin embargo, de vez en cuando TreeView está completamente en blanco, sin nodos en absoluto. Incluso copié TreeView en una página de contenido. La página de contenido TreeView siempre funciona, incluso cuando MasterPage no lo hace. (¡Tampoco sabía que un control en una página de contenido podría usar una fuente de datos en una página maestra hasta que olvidé copiar la fuente de datos!)
Intentando depurar eso, puse una excepción de lanzamiento en mi función BuildSiteMap () en SiteMapProvider solo para probarme a mí mismo que el código realmente se estaba ejecutando. Lo que encontré fue que la excepción fue golpeada cada vez. Sin embargo, el seguimiento de la pila no fue el mismo cada vez.
La mayoría de las veces, esto es lo que obtuve:
[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
Sin embargo, casi tan a menudo como TreeView se queda en blanco, obtuve esto:
[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
Supongo que el bit de código útil sería la función 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 () y AddFiles () simplemente hacen más de lo mismo, así que por brevedad los dejaré fuera a menos que alguien piense que son importantes.
Traté de publicar el código para la vista de árbol aquí, pero parece que al sitio realmente no le gusta eso. Diré que estoy configurando la propiedad DataSourceID en lugar de asignarla en tiempo de ejecución. Lo intenté en ambos sentidos, no parece hacer la diferencia.
No estoy realmente seguro de qué más podría ser útil, así que avíseme si necesita más detalles.
Ahora me pregunto si esto podría ser una pista de mi problema o si es solo una coincidencia. Si es una pista, soy demasiado denso para entenderlo. ¿Algo de esto tiene sentido para alguien más?
Solución
Como resultado, el problema estaba en un código que no creía que valiera la pena publicar. Parece que cada ejemplo que he encontrado hace algo como esto:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
Return siteRoot
End Function
Resulta que GetRootNodeCore () se llama prácticamente desde el principio, por lo que a veces siteRoot no es nada. Entonces la solución es la siguiente:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
If siteRoot Is Nothing Then
SyncLock Me
BuildSiteMap()
End SyncLock
End If
Return siteRoot
End Function
No me daré crédito por encontrar eso por mi cuenta, alguien me lo señaló aquí: http://forums.asp.net/p/1473236/3420805.aspx#3420805