title: ASP.Net TreeView control on MasterPage isn't always populated
body: <p>I'm working on my first ever ASP.Net project, and I seem to have been thrown in the deep end right away.  All of my site files are stored in a database, so I'm using a VirtualPathProvider to access them.  That part works well, but then I needed a site map that would dynamically pick up all the files since the user will add/delete files as they go.  To do that, I created a class that inherits StaticSiteMapProvider, created a SiteMapDataSource on my Master Page, and a TreeView to use it.  For the most part, this works.  When you load the page you see the TreeView and it contains all of the nodes it is supposed to.  However, every now and then the TreeView is completely blank -- no nodes at all.  I even copied the TreeView into a content page.  The content page TreeView always works, even when the MasterPage doesn't.  (Also I didn't know a control on a content page could use a data source on a master page until I forgot to copy the data source!)</p>
  
  <p>Trying to debug that, I put a throw exception in my BuildSiteMap() function in the SiteMapProvider just to prove to myself that the code was actually running.  What I found was that the exception was hit every single time.  However, the stack trace wasn't the same every time.</p>
  
  <p>Most of the time, this is what I got:</p>
  
  <pre>
  [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
  </pre>
  
  <p>However, about as often as the TreeView would come up blank, I got this:</p>
  
  <pre>
      [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
  </pre>
  
  <p>I guess the useful bit of code would be the BuildSiteMap function:</p>
  
  <p><code></p>
  
  <pre><code>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
  </code></pre>
  
  <p></code></p>
  
  <p>AddFolders() and AddFiles() just do more of the same, so for brevity's sake I'll leave them out unless someone thinks they are important.</p>
  
  <p>I tried to post the code for the treeview here, but it seems the site doesn't really like that.  I will say that I'm setting the DataSourceID property instead of assigning it at runtime.  I tried it both ways, doesn't seem to make a difference.</p>
  
  <p>I'm not really sure what else might be useful, so just let me know if you need any more details.</p>
  
  <p>Now I'm left wondering if this could be a clue to my problem or if it's just a coincidence.  If it's a clue, I'm too dense to figure it out.  Does any of this make sense to anyone else?</p>