Элемент управления ASP.Net TreeView на MasterPage не всегда заполнен - PullRequest
2 голосов
/ 19 сентября 2009

Я работаю над своим первым в истории проектом 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:

</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

AddFolders () и AddFiles () просто делают больше того же самого, поэтому для краткости я их опущу, если кто-то не считает их важными.

Я попытался опубликовать здесь код для дерева, но, похоже, сайту это не очень нравится. Я скажу, что я устанавливаю свойство DataSourceID вместо назначения его во время выполнения. Я пробовал оба пути, похоже, ничего не изменилось.

Я не совсем уверен, что еще может быть полезным, поэтому просто дайте мне знать, если вам нужно больше подробностей.

Теперь я задаюсь вопросом, может ли это быть ключом к моей проблеме или это просто совпадение. Если это подсказка, я слишком глуп, чтобы понять это. Имеет ли это какое-либо значение для кого-либо еще?

1 Ответ

0 голосов
/ 23 сентября 2009

Как оказалось, проблема заключалась в небольшом количестве кода, который я не думал, что стоит публиковать. Кажется, что каждый пример, который я нашел, делает что-то вроде этого:

</p> <pre><code> Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode Return siteRoot End Function

Оказывается, что GetRootNodeCore () вызывается практически сразу из шлюза, поэтому иногда siteRoot - ничто. Таким образом, решение заключается в следующем:

</p> <pre><code>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

...