Creating an ASP.NET SiteMap dynamically using LINQ and bind to a TreeView

Posted by: Suprotim Agarwal , on 1/25/2009, in Category ASP.NET
Views: 54094
Abstract: I had recently posted an article ASP.NET TreeView and SiteMap : 5 Common Tips. A viewer mailed me back asking if it was possible to create a SiteMap dynamically and add it to a TreeView. This short and simple article demonstrates how to create an ASP.NET SiteMap file dynamically and bind it to a TreeView control.
Creating an ASP.NET SiteMap dynamically using LINQ and bind to a TreeView
 
I had recently posted an article ASP.NET TreeView and SiteMap : 5 Common Tips. A viewer mailed me back asking if it was possible to create a SiteMap dynamically and add it to a TreeView. This short and simple article demonstrates how to create an ASP.NET SiteMap file dynamically and bind it to a TreeView control.
SiteMap is an XML file. You can use both the System.XML.Linq.XDocument and System.XML.Linq.XElement classes to create XML.  When you need to create an XML document containing XML declaration, XML Document Type (DTD), Processing instructions, Comments or Namespaces, you should go in for the XDocument class. Here’s how to create and save a SiteMap file dynamically using LINQ
Drag and drop a Button and a TreeView control from the toolbox to the Default.aspx page
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnCreate" runat="server"
            Text="Create and Bind" />
        <br />
        <br />
        <asp:TreeView ID="TreeView1" runat="server">
        </asp:TreeView>
    </div>
    </form>
</body>
Now add the following code on the click event of the button
C#
    protected void btnCreate_Click(object sender, EventArgs e)
    {
        XNamespace siteNM = "http://schemas.microsoft.com/AspNet/SiteMap-File-1.0";
 
        XDocument xDoc = new XDocument(
                    new XDeclaration("1.0", "UTF-8", null),
                    new XElement(siteNM + "siteMap",
                        new XElement(siteNM + "siteMapNode", new XAttribute("title", "My Favorites"),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "Favorite Sites"),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "ASP.NET Home"), new XAttribute("url", "http://www.asp.net")),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "ASP.NET Articles"), new XAttribute("url", "https://www.dotnetcurry.com")),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "Windows Client"), new XAttribute("url", "http://www.windowsclient.net")),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "Silverlight"), new XAttribute("url", "http://silverlight.net"))
                            ),
 
                        new XElement(siteNM + "siteMapNode", new XAttribute("title", "Favorite Blogs"),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "ScottGu Blog"), new XAttribute("url", "http://weblogs.asp.net/scottgu"),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "Technology Blog"), new XAttribute("url", "http://www.devcurry.com")),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "SQL Blog"), new XAttribute("url", "http://www.sqlservercurry.com")),
                            new XElement(siteNM + "siteMapNode", new XAttribute("title", "Food Lovers"), new XAttribute("url", "http://foodatarian.com"))
                            )) )                          
                           
                            ));
      
       
        // Save to Disk
        xDoc.Save(Server.MapPath("web.sitemap"));
       
    }
VB.NET
        Protected Sub btnCreate_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim siteNM As XNamespace = "http://schemas.microsoft.com/AspNet/SiteMap-File-1.0"
 
        Dim xDoc As New XDocument(New XDeclaration("1.0", "UTF-8", Nothing), _
          New XElement(siteNM + "siteMap", _
                       New XElement(siteNM + "siteMapNode", New XAttribute("title", "My Favorites"), _
                                    New XElement(siteNM + "siteMapNode", New XAttribute("title", "Favorite Sites"), _
                                                 New XElement(siteNM + "siteMapNode", New XAttribute("title", "ASP.NET Home"), New XAttribute("url", "http://www.asp.net")), _
                                                 New XElement(siteNM + "siteMapNode", New XAttribute("title", "ASP.NET Articles"), New XAttribute("url", "https://www.dotnetcurry.com")), _
                                                 New XElement(siteNM + "siteMapNode", New XAttribute("title", "Windows Client"), New XAttribute("url", "http://www.windowsclient.net")), _
                                                 New XElement(siteNM + "siteMapNode", New XAttribute("title", "Silverlight"), New XAttribute("url", "http://silverlight.net"))), _
                                    New XElement(siteNM + "siteMapNode", New XAttribute("title", "Favorite Blogs"), _
                                                 New XElement(siteNM + "siteMapNode", New XAttribute("title", "ScottGu Blog"), New XAttribute("url", "http://weblogs.asp.net/scottgu"), _
                                                              New XElement(siteNM + "siteMapNode", New XAttribute("title", "Technology Blog"), New XAttribute("url", "http://www.devcurry.com")), _
                                                              New XElement(siteNM + "siteMapNode", New XAttribute("title", "SQL Blog"), New XAttribute("url", "http://www.sqlservercurry.com")), _
                                                              New XElement(siteNM + "siteMapNode", New XAttribute("title", "Food Lovers"), New XAttribute("url", "http://foodatarian.com")))))))
 
 
        ' Save to Disk
        xDoc.Save(Server.MapPath("web.sitemap"))
    End Sub
 
Note: As you might have observed, I have added a namespace for each element. Here all elements use one namespace. In case you don't add a namespace for one parent element, it will add a empty namespace (xmlns=””) and the compiler will raise a warning “The element 'siteMap' in namespace 'http://schemas.microsoft.com/AspNet/SiteMap-File-1.0' has invalid child element 'siteMapNode’ “. Hence the trick is to add a namespace for each element.
Once the SiteMap is created, in order to bind it to the TreeView, all that is needed is to create a SiteMapDataSource and bind it to the TreeView
C#
...
        // Save to Disk
        xDoc.Save(Server.MapPath("web.sitemap"));
        if(File.Exists(Server.MapPath("web.sitemap")))
        {          
            TreeView1.DataSource = new SiteMapDataSource();
            TreeView1.DataBind();
        }
VB.NET
...
 
        ' Save to Disk
        xDoc.Save(Server.MapPath("web.sitemap"))
        If File.Exists(Server.MapPath("web.sitemap")) Then
            TreeView1.DataSource = New SiteMapDataSource()
            TreeView1.DataBind()
        End If
The result is a dynamically created SiteMap bound to a TreeView control
Dynamic TreeView
I hope you liked the article and I thank you for viewing it.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of DotNetCurry, DNC Magazine for Developers, SQLServerCurry and DevCurry. He has also authored a couple of books 51 Recipes using jQuery with ASP.NET Controls and The Absolutely Awesome jQuery CookBook.

Suprotim received the prestigious Microsoft MVP award for 17 consecutive years, until he resigned from the program in 2025. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.

Get in touch with him on Twitter @suprotimagarwal or at LinkedIn



Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by SnovvWolf on Wednesday, February 25, 2009 3:31 PM
This article explains how to create and save an xml file, and then how to bind it to a treeview, but I think it falls far short of what the title promises. The xml is populated using hardcoded urls. (Which would be totally fine for an example that wasn't titled "Creating an ASP.NET SiteMap dynamically..."

I would have expected that this should contain a routine that accepts a starting url and then traverses the website and picks up the website hierarchy "dynamically" and construct the xml accordingly.

Why would anyone hand-code an xml file as proposed above? Look ma, I'm linq'ing.

I'm rating this 3 just because there's some value to the article, just not the intended value. It's misleading.

For 5 stars, rename it to "How to bind xml to a treeview with 2 lines of code + 40 lines of code you should ignore".
Comment posted by Suprotim Agarwal on Thursday, February 26, 2009 6:36 AM
SnovvWolf: Thanks for your comments. Apologies if the title was misleading but the intention was to show how to create a SiteMap using LINQ and bind it to a TreeView. Usually a SiteMap would depict links within the site. However the scenario of fetching links dyanamically is not too difficult to achive and especially with LINQ, it shouldn't be much of a pain either.

Watch out for another article in a couple of days which will show how to query the sitemap using LINQ. I do not know if I will cover fetching the url's dynamically, but it's going to be an interesting read!
Comment posted by PA on Friday, October 9, 2009 6:10 AM
I tried the code. The sitemap file get's created, by there's an exception [Object reference not set to an instance of an object] for
TreeView1.DataSource = new SiteMapDataSource();

Any help there ?
Comment posted by RF on Thursday, December 10, 2009 5:12 AM
dddd
Comment posted by annoyed on Friday, June 11, 2010 5:06 AM
Why you titled it "Creating an ASP.NET SiteMap dynamically using LINQ and bind to a TreeView" is beyond me. Theres nothing dynamic about it. You've hard coded the whole thing. Thx for wasting my time!
Comment posted by dil on Thursday, September 9, 2010 7:15 AM
it is very use ful for me
Comment posted by Jethro on Friday, August 19, 2011 3:01 PM
Any chance you could provide a sample that does not create the sitemap in a single command?  Everything works, but using the continuation lines does not allow me to create one node at a time, which would be necessary to dynamically create a site map.  I could do it by dynamically creating the command itself, but I don't want to do that.  Thanks.
Comment posted by MT on Tuesday, November 8, 2011 3:10 AM
did you ever write that article how to do this with linq I would very much like to see it...im working on a site right now where I have to generate an xmlsitemap from database I have a proc that gets the data for the sitemap from the database but dont know how I will implement it to work with this. Thanks
Comment posted by MT on Friday, November 11, 2011 2:42 AM
did you ever write that article how to do this with linq I would very much like to see it...im working on a site right now where I have to generate an xmlsitemap from database I have a proc that gets the data for the sitemap from the database but dont know how I will implement it to work with this. Thanks
Comment posted by Hazel on Sunday, December 21, 2014 9:17 PM
How do you do it when the XElement is retrieve from database..really need help. TQ
$(this).siblings('.current').removeClass('current'); $(this).addClass('current'); $('.tabContent').children('.current').removeClass('current'); $('.tabContent').children().eq($(this).index()).addClass('current'); }); });