MasterPage 上的 ASP.Net TreeView 控件并不总是填充

发布于 2024-08-05 18:44:54 字数 4504 浏览 4 评论 0原文

我正在开发我的第一个 ASP.Net 项目,我似乎立刻就陷入了困境。我的所有站点文件都存储在数据库中,因此我使用 VirtualPathProvider 来访问它们。该部分效果很好,但后来我需要一个可以动态拾取所有文件的站点地图,因为用户将随时添加/删除文件。为此,我创建了一个继承 StaticSiteMapProvider 的类,在我的母版页上创建了一个 SiteMapDataSource,并创建了一个 TreeView 来使用它。在大多数情况下,这是有效的。当您加载页面时,您会看到 TreeView,它包含它应该包含的所有节点。然而,TreeView 有时会完全空白——根本没有节点。我什至将 TreeView 复制到内容页面中。即使 MasterPage 不起作用,内容页 TreeView 也始终起作用。 (另外,我不知道内容页上的控件可以使用母版页上的数据源,直到我忘记复制数据源!)

尝试调试它,我在 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 属性,而不是在运行时分配它。我尝试了两种方法,似乎没有什么区别。

我不太确定还有什么可能有用,所以如果您需要更多详细信息,请告诉我。

现在我想知道这是否是解决我的问题的线索,或者这只是一个巧合。如果这是一条线索,我太笨了,无法弄清楚。这些对其他人来说有意义吗?

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!)

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.

Most of the time, this is what I got:

[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

However, about as often as the TreeView would come up blank, I got this:

    [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

I guess the useful bit of code would be the BuildSiteMap function:

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() and AddFiles() just do more of the same, so for brevity's sake I'll leave them out unless someone thinks they are important.

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.

I'm not really sure what else might be useful, so just let me know if you need any more details.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枫以 2024-08-12 18:44:54

事实证明,问题出在一些我认为不值得发布的代码中。似乎我发现的每个示例都执行类似以下操作:

 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

As it turns out, the problem was in a bit of code that I didn't think was worth posting. It seems that every example I've found does something like this:

 Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
     Return siteRoot
 End Function

It turns out that GetRootNodeCore() gets called pretty much right out of the gate, so sometimes siteRoot is nothing. So the solution is as follows:

Protected Overrides Function GetRootNodeCore() As System.Web.SiteMapNode
    If siteRoot Is Nothing Then
        SyncLock Me
            BuildSiteMap()
        End SyncLock
    End If

    Return siteRoot
End Function

I won't take credit for finding that on my own, someone pointed it out to me here: http://forums.asp.net/p/1473236/3420805.aspx#3420805

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文