因为我的做的一个项目是基于Category分类来进行导航的, 查看
ASP.NET 站点导航概述 和 
如何:实现 ASP.NET 站点地图提供程序  两篇参考文章, 也模仿地写了一个SiteMapProvider程序....
各个 ASP.NET 站点导航组件之间的关系图
![站点导航类之间的关系]()
而我们这次就是编程图中的"自定义站点地图提供程序"....
我的DAL层是基于NBear的....
Category实体定义如下:
[AutoPreLoad]
    public interface Category : Entity
    {
        [PrimaryKey]
        int ID { get; }
        [SqlType("nvarchar(50)")]
        string Title { get; set; }
        /// <summary>
        /// 排序位置
        /// </summary>
        int Sort { get;set;}
        [FkReverseQuery(LazyLoad = true)]
        [MappingName("ParentID")]
        Category Parent { get;set;}
        [FkQuery("Parent", LazyLoad = false, OrderBy= "Sort")]
        [SerializationIgnore]
        Category[] Children { get; set; }
        [FkQuery("Category", OrderBy = "{ID} DESC", LazyLoad = true)]
        Article[] Articles { get;set;}
    }
程序代码如下:
![]()
![]() MK2.AspNet.Controls.AccessSiteMapProvider
MK2.AspNet.Controls.AccessSiteMapProvider 
namespace MK2.AspNet.Controls
{
    using System;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Data;
    using System.Data.OleDb;
    using System.Security.Permissions;
    using System.Web;
    using Entities;
    /// An extremely simple AccessSiteMapProvider that only supports a
    /// site map node hierarchy 1 level deep.
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class AccessSiteMapProvider : StaticSiteMapProvider
    {
        private SiteMapNode rootNode = null;
        private CategoryDAL categoryDAL = null;
        // Implement a default constructor.
        public AccessSiteMapProvider() { }
        // Some basic state to help track the initialization state of the provider.
        private bool initialized = false;
        public virtual bool IsInitialized
        {
            get
            {
                return initialized;
            }
        }
        // Return the root node of the current site map.
        public override SiteMapNode RootNode
        {
            get
            {
                SiteMapNode temp = null;
                temp = BuildSiteMap();
                return temp;
            }
        }
        protected override SiteMapNode GetRootNodeCore()
        {
            return RootNode;
        }
        // Initialize is used to initialize the properties and any state that the
        // AccessProvider holds, but is not used to build the site map.
        // The site map is built when the BuildSiteMap method is called.
        public override void Initialize(string name, NameValueCollection attributes)
        {
            if (IsInitialized)
                return;
            base.Initialize(name, attributes);
            // Create and test the connection to the Microsoft Access database.
            categoryDAL = new CategoryDAL();
            initialized = true;
        }
        ///
        /// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override.
        ///
        // Clean up any collections or other state that an instance of this may hold.
        protected override void Clear()
        {
            lock (this)
            {
                rootNode = null;
                base.Clear();
            }
        }
        // Build an in-memory representation from persistent
        // storage, and return the root node of the site map.
        public override SiteMapNode BuildSiteMap()
        {
            // Since the SiteMap class is static, make sure that it is
            // not modified while the site map is built.
            lock (this)
            {
                // If there is no initialization, this method is being
                // called out of order.
                if (!IsInitialized)
                {
                    throw new Exception("BuildSiteMap called incorrectly.");
                }
                // If there is no root node, then there is no site map.
                if (null == rootNode)
                {
                    // Start with a clean slate
                    Clear();
                    // Select the root node of the site map from Microsoft Access.
                    rootNode = new SiteMapNode(this, "-1", "~/", "首页", "Home page.");
                    Category[] childNodes = categoryDAL.GetCategories(0);
                    foreach (Category child in childNodes)
                    {
                        SiteMapNode childNode;
                        childNode = GetNode(child);
                        AddNode(childNode, rootNode);
                    }
                }
                return rootNode;
            }
        }
        private SiteMapNode GetNode(Category node)
        {
            SiteMapNode returnNode = new SiteMapNode(this, node.ID.ToString(),
                    "~/Category.aspx?Category=" + node.ID, node.Title, node.Title);
            if (node.Children.Count > 0)
            {
                foreach (Category child in node.Children)
                {
                    SiteMapNode childNode;
                    childNode = GetNode(child);
                    AddNode(childNode, returnNode);
                }
            }
            return returnNode;
        }
    }
}此SiteMapProvider只适合我的项目, 在此只是作个示例展示如何扩展StaticSiteMapProvider而已....