Элемент управления ASP.Net TreeView на MasterPage не всегда заполнен
-
22-07-2019 - |
Вопрос
Я работаю над своим первым проектом ASP.Net, и мне кажется, что меня сразу бросили в глубокий конец. Все файлы моего сайта хранятся в базе данных, поэтому я использую VirtualPathProvider для доступа к ним. Эта часть работает хорошо, но тогда мне понадобилась карта сайта, которая будет динамически подбирать все файлы, так как пользователь будет добавлять / удалять файлы по мере их поступления. Для этого я создал класс, который наследует StaticSiteMapProvider, создал SiteMapDataSource на моей мастер-странице и TreeView для его использования. По большей части это работает. Когда вы загружаете страницу, вы видите TreeView, и он содержит все узлы, которые он должен. Тем не менее, время от времени TreeView полностью пуст - никаких узлов вообще нет. Я даже скопировал TreeView на страницу контента. Страница содержимого TreeView всегда работает, даже если MasterPage не работает. (Также я не знал, что элемент управления на странице содержимого может использовать источник данных на главной странице, пока я не забуду скопировать источник данных!)
Пытаясь отладить это, я поместил исключение throw в мою функцию BuildSiteMap () в SiteMapProvider, просто чтобы доказать себе, что код действительно выполняется. Я обнаружил, что исключение было совершено каждый раз. Однако трассировка стека не всегда была одинаковой.
Большую часть времени это то, что я получил:
[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
Однако примерно так же часто, как TreeView будет пустым, я получил следующее:
[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
Полагаю, полезным фрагментом кода была бы функция 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 () и AddFiles () просто делают больше того же самого, поэтому для краткости я их опущу, если кто-то не считает их важными.
Я попытался опубликовать здесь код для дерева, но, похоже, сайту это не очень нравится. Я скажу, что я устанавливаю свойство DataSourceID вместо назначения его во время выполнения. Я пробовал оба пути, похоже, ничего не изменилось.
Я не совсем уверен, что еще может быть полезно, поэтому просто дайте мне знать, если вам нужно больше подробностей.
Теперь мне остается только подумать, может ли это быть ключом к моей проблеме или это просто совпадение. Если это подсказка, я слишком глуп, чтобы понять это. Имеет ли это какое-то значение для кого-то еще?
Решение
Как выяснилось, проблема заключалась в небольшом количестве кода, который, как я думал, не стоил публиковать. Кажется, что каждый пример, который я нашел, делает что-то вроде этого:
<код> код>
<код> Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
Return siteRoot
End Function
Код> <код> код>
Оказывается, что GetRootNodeCore () вызывается почти сразу же, поэтому иногда siteRoot - ничто. Таким образом, решение заключается в следующем:
<код> код>
<код>Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
If siteRoot Is Nothing Then
SyncLock Me
BuildSiteMap()
End SyncLock
End If
Return siteRoot
End Function
Код> <код> код>
Я не возьму на себя ответственность за то, что нашел это самостоятельно, кто-то указал мне здесь: http://forums.asp.net/p/1473236/3420805.aspx#3420805