Le contrôle TreeView ASP.Net sur MasterPage n'est pas toujours rempli
-
22-07-2019 - |
Question
Je suis en train de travailler sur mon tout premier projet ASP.Net, et il semble que je sois tombé dans le vif du sujet tout de suite. Tous les fichiers de mon site sont stockés dans une base de données, j'utilise donc un VirtualPathProvider pour y accéder. Cette partie fonctionne bien, mais il me fallait alors un plan du site qui récupère de manière dynamique tous les fichiers, car l'utilisateur ajoute / supprime des fichiers au fur et à mesure. Pour ce faire, j'ai créé une classe qui hérite de StaticSiteMapProvider, créé un SiteMapDataSource sur ma page maître et un TreeView pour l'utiliser. Pour la plupart, cela fonctionne. Lorsque vous chargez la page, vous voyez TreeView et il contient tous les nœuds auxquels il est censé être associé. Cependant, de temps en temps, TreeView est complètement vide - pas de nœuds du tout. J'ai même copié le TreeView dans une page de contenu. La page de contenu TreeView fonctionne toujours, même lorsque MasterPage ne fonctionne pas. (En outre, je ne savais pas qu'un contrôle sur une page de contenu pouvait utiliser une source de données sur une page maître jusqu'à ce que j'oublie de copier la source de données!)
En essayant de déboguer cela, je mets une exception de projection dans ma fonction BuildSiteMap () dans SiteMapProvider, juste pour me prouver que le code était en cours d'exécution. Ce que j'ai trouvé, c'est que l'exception a été touchée à chaque fois. Cependant, la trace de la pile n’est pas toujours la même.
La plupart du temps, voici ce que j'ai eu:
[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
Cependant, à peu près aussi souvent que TreeView venait à blanc, j'ai ceci:
[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
Je suppose que le bit de code utile serait la fonction 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 () et AddFiles () font juste plus de la même chose, donc par souci de brièveté, je les laisserai tomber sauf si quelqu'un pense qu'ils sont importants.
J'ai essayé de poster le code de l'arborescence ici, mais il semble que le site n'aime pas vraiment cela. Je dirai que je mets la propriété DataSourceID au lieu de l'attribuer à l'exécution. Je l'ai essayé dans les deux sens, ne semble pas faire de différence.
Je ne suis pas vraiment sûr de ce qui pourrait être utile, alors laissez-moi savoir si vous avez besoin de plus de détails.
Maintenant, je me demande si cela pourrait être un indice de mon problème ou s'il ne s'agit que d'une coïncidence. Si c'est un indice, je suis trop dense pour le comprendre. Est-ce que cela a du sens pour quelqu'un d'autre?
La solution
Il s’est avéré que le problème tenait à un peu de code qui, à mon avis, ne valait pas la peine d’être publié. Il semble que chaque exemple que j'ai trouvé fasse quelque chose comme ceci:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
Return siteRoot
End Function
Il se trouve que GetRootNodeCore () est appelé assez rapidement, donc parfois, siteRoot n’est rien. La solution est donc la suivante:
Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
If siteRoot Is Nothing Then
SyncLock Me
BuildSiteMap()
End SyncLock
End If
Return siteRoot
End Function
Je ne prendrai pas le mérite de l'avoir découvert seul, quelqu'un me l'a fait remarquer ici: http://forums.asp.net/p/1473236/3420805.aspx#3420805