C# Sitemap Uses LINQ

Dot Net Perls
Note (please read)

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. Here we look at an example implementation of sitemaps in LINQ and the C# language.

Introduction

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.

Example

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.

Program that initializes sitemap array [C#]

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());
    }

    /// <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();
    }
}

Output

<div>
  <a href="Default.aspx">Blank</a>
  <a href="Content/Find-First-Set-Cpp.aspx">Find First Set C++</a>
</div>

Description. 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.

Singletons

Number 1

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.

Groupby operator

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.

Group By Operator

Summary

LINQ (language integrated query)

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. LINQ doesn't involve any confusing casts or complicated database connections. LINQ queries provide easier sorting and categorization, and are stateless and extremely flexible.

LINQ Examples