Problem. You want to use LINQ in ASP.NET to query your sitemap data structure. Often, using the Web.sitemap in its default form is sufficient, but here we need a more flexible solution that allows us to generate Google XML sitemaps, and more. Solution. Here we look at an example implementation of sitemaps in LINQ.
First, the data source format is not important. It can be in a database, an XML file, or just custom object arrays in code. The data source contains a series of nodes, one for each page in the site, and each node can have any number of properties.
Property: Visibility
Url
Title
Data type: VisibilityType enum
String
String
Usage: Where the page is presented on the site.
Where the page is stored in the project.
What the page's title is.Description of following code. The code that follows contains the class definition of a single page in the ASP.NET web site's sitemap. It shows the declaration of the data, which will be different in your project. Finally, it has the GetArchiveString method, which builds up the HTML from the object array.
using System;
using System.Linq;
using System.Xml.Linq;
class Program
{
static void Main()
{
_pages = new SitePage[]
{
new SitePage
{
Visibility = VisibilityType.Archive, // Root page
Url = "Default.aspx", // Url
Title = "Blank" // Title
},
new SitePage
{
Visibility = VisibilityType.Regular,
Url = "Content/Anagram-Web-Database.aspx",
Title = "Anagram Database Web Application",
},
new SitePage
{
Visibility = VisibilityType.Archive,
Url = "Content/Find-First-Set-Cpp.aspx",
Title = "Find First Set C++",
}
};
Console.WriteLine(GetArchiveString());
// <div>
// <a href="Default.aspx">Blank</a>
// <a href="Content/Find-First-Set-Cpp.aspx">Find First Set C++</a>
// </div>
}
/// <summary>
/// Enum for visibility of page.
/// </summary>
public enum VisibilityType
{
Archive,
Regular,
Root
}
/// <summary>
/// A single object that corresponds to a page.
/// </summary>
public class SitePage
{
/// <summary>
/// The visibility level of the page.
/// </summary>
public VisibilityType Visibility { get; set; }
/// <summary>
/// The page's title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// The page URL
/// </summary>
public string Url { get; set; }
}
/// <summary>
/// Array of pages.
/// </summary>
static SitePage[] _pages;
/// <summary>
/// Get the page archive string.
/// </summary>
public static string GetArchiveString()
{
XElement pageList = new XElement("div", from page in _pages
where page.Visibility == VisibilityType.Archive
orderby page.Title
select new XElement("a",
new XAttribute("href", page.Url),
page.Title));
return pageList.ToString();
}
}Description of LINQ query. This is an example of a LINQ query. First, the LINQ query takes each page from the _pages array in this class, and sees if the page has a VisibilityType of Archive. It then alphabetizes based on the Title property. Finally, it selects each page and returns them all.
For global, single-instance data like this, use a singleton pattern. The singleton pattern saves memory and enhances performance and will allow for cleaner code. I use a master page for the site. On the master page file, you can simply do a Response.Write of a function call to your custom sitemap.
For a hierarchal, tree-like sidebar, you can use the groupby operator to group the categories, alphabetize them, and then alphabetize their pages. groupby allows you to generate IGrouping enumerables, which are fairly simple to use in foreach loops. [GroupBy Operator - Hooked on LINQ - hookedonlinq.com]
Jim Wooley suggested some enhancements to this code, concerning projecting the HTML to the string. This makes the code much clearer and easier to maintain. He has another example of a Linq sitemap on his site. [Adding a dynamic SiteMap for search engine optimization using LINQ - thinqlinq.com]
Here we saw an example of how you can use LINQ to project an HTML fragment that can be used for navigation on your website. You can substitute the object collection shown with XML or database data.
Note on SQL. Everything above could be done in SQL, but it is all on in-memory object arrays here. LINQ doesn't involve any confusing casts or complicated database connections. LINQ queries provide easier sorting and categorization, and are stateless and extremely flexible.