关键
1、创建.sitemap文件,其实就是一个xml文件,包括有着层次结构的元素
2、元素的属性:
 Url - 链接地址
 Title - 显示的标题
 Description - 描述(ToolTip)
 resourceKey - 本地化用的(要在节点加上这个属性enableLocalization=true) 
 securityTrimmingEnabled - 是否让sitemap支持安全特性
 roles - 哪些角色可以访问当前节点,多角色用逗号隔开(需要将securityTrimmingEnabled设置为true)
 siteMapFile - 引用另一个sitemap文件
 注:应用权限的时候,Web.config中的SiteMap节点的Provider也要有相对应的配置(securityTrimmingEnabled="true")
3、可以通过SiteMap和SiteMapNode类访问站点地图数据
4、自定义站点地图提供程序应该写一个继承自StaticSiteMapProvider的类
5、XmlSiteMapProvider要求站点地图节点具有唯一的URL
示例
SiteMap/Web.sitemap(包括一个有siteMapFile属性的节点)
 
 
 
 
 
 
 
SiteMap/WebChild.sitemap(上面.sitemap文件某个节点的siteMapFile属性所指定的文件)
 
 
 
 
 
站点地图测试
SiteMap/Test.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Test.aspx.cs"
 Inherits="SiteMap_Test" Title="站点地图测试" %>
 
 
 
 
 <%--显示根节点的数据源--%>
 
 <%--不显示根节点的数据源--%>
  ShowStartingNode="false" />
 
 
 编码方式访问节点信息如下
 
 
SiteMap/Test.aspx.cs
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public partial class SiteMap_Test : System.Web.UI.Page
{
 protected void Page_Load(object sender, EventArgs e)
 {
 // 获取当前节点的Title
 lbl.Text = "当前节点标题:" + SiteMap.CurrentNode.Title + "
";
 // 取得url为“~/Default.aspx”的SiteMapNode
 SiteMapNode smn = SiteMap.Provider.FindSiteMapNode("~/Default.aspx");
 lbl.Text += "Default.aspx节点的Url:" + smn.Url;
 }
}
站点地图测试(从数据库读数据)
SiteMap/FromDatabase.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="FromDatabase.aspx.cs"
 Inherits="SiteMap_FromDatabase" Title="站点地图测试(从数据库读数据)" %>
 
 
 
自定义站点地图提供程序(SqlServer方式)
SqlSiteMapProvider.cs(“sp_GetSiteMap”为读取站点地图数据的存储过程,详见源码)
using System;
using System.Web;
using System.Data.SqlClient;
using System.Collections.Specialized;
using System.Configuration;
using System.Web.Configuration;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Security.Permissions;
using System.Data.Common;
using System.Data;
/**//// 
/// SqlSiteMapProvider
/// 
public class SqlSiteMapProvider : StaticSiteMapProvider
{
 private string _strCon;
 private int _indexID, _indexTitle, _indexUrl, _indexDesc, _indexParent;
 // 节点
 private SiteMapNode _node;
 
 // 节点字典表
 private Dictionary _nodes = new Dictionary();
 
 // 用于单例模式
 private readonly object _lock = new object();
 /**//// 
 /// 初始化
 /// 
 /// name
 /// config
 public override void Initialize(string name, NameValueCollection config)
 {
 // 验证是否有config
 if (config == null)
 throw new ArgumentNullException("config不能是null");
 // 没有provider则设置为默认的
 if (String.IsNullOrEmpty(name))
 name = "SqlSiteMapProvider";
 // 没有描述就增加一个描述
 if (string.IsNullOrEmpty(config["description"]))
 {
 config.Remove("description");
 config.Add("description", "SqlSiteMapProvider");
 }
 // 调用基类的初始化方法
 base.Initialize(name, config);
 // 初始化连接字符串
 string conStringName = config["connectionStringName"];
 if (String.IsNullOrEmpty(conStringName))
 throw new ProviderException("没找到connectionStringName");
 config.Remove("connectionStringName");
 if (WebConfigurationManager.ConnectionStrings[conStringName] == null)
 throw new ProviderException("根据connectionStringName没找到连接字符串");
 // 获得连接字符串
 _strCon = WebConfigurationManager.ConnectionStrings[conStringName].ConnectionString;
 if (String.IsNullOrEmpty(_strCon))
 throw new ProviderException("连接字符串是空的");
 }
 /**//// 
 /// 从持久性存储区加载站点地图信息,并在内存中构建它
 /// 
 /// 
 public override SiteMapNode BuildSiteMap()
 {
 lock (_lock)
 {
 // 单例模式的实现
 if (_node != null)
 return _node;
 SqlConnection connection = new SqlConnection(_strCon);
 try
 {
 SqlCommand command = new SqlCommand("sp_GetSiteMap", connection);
 command.CommandType = CommandType.StoredProcedure;
 connection.Open();
 SqlDataReader reader = command.ExecuteReader();
 // 获得各个字段的索引
 _indexID = reader.GetOrdinal("ID");
 _indexUrl = reader.GetOrdinal("Url");
 _indexTitle = reader.GetOrdinal("Title");
 _indexDesc = reader.GetOrdinal("Description");
 _indexParent = reader.GetOrdinal("Parent");
 if (reader.Read())
 {
 // 把第一条记录作为根节点添加
 _node = CreateSiteMapNodeFromDataReader(reader);
 AddNode(_node, null);
 // 构造节点树
 while (reader.Read())
 {
 // 在站点地图中增加一个节点
 SiteMapNode node = CreateSiteMapNodeFromDataReader(reader);
 AddNode(node, GetParentNodeFromDataReader(reader));
 }
 }
 reader.Close();
 }
 catch (Exception ex)
 {
 throw new Exception(ex.ToString());
 }
 finally
 {
 connection.Close();
 }
 // 返回SiteMapNode
 return _node;
 }
 }
 /**//// 
 /// 将检索目前由当前提供程序管理的所有节点的根节点
 /// 
 /// 
 protected override SiteMapNode GetRootNodeCore()
 {
 lock (_lock)
 {
 return BuildSiteMap();
 }
 }
 /**//// 
 /// 根据DataReader读出来的数据返回SiteMapNode
 /// 
 /// DbDataReader
 /// 
 private SiteMapNode CreateSiteMapNodeFromDataReader(DbDataReader reader)
 {
 if (reader.IsDBNull(_indexID))
 throw new ProviderException("没找到ID");
 int id = reader.GetInt32(_indexID);
 if (_nodes.ContainsKey(id))
 throw new ProviderException("不能有重复ID");
 // 根据字段索引获得相应字段的值
 string title = reader.IsDBNull(_indexTitle) ? null : reader.GetString(_indexTitle).Trim();
 string url = reader.IsDBNull(_indexUrl) ? null : reader.GetString(_indexUrl).Trim();
 string description = reader.IsDBNull(_indexDesc) ? null : reader.GetString(_indexDesc).Trim();
 // 新建一个SiteMapNode
 SiteMapNode node = new SiteMapNode(this, id.ToString(), url, title, description);
 // 把这个SiteMapNode添加进节点字典表里
 _nodes.Add(id, node);
 // 返回这个SiteMapNode
 return node;
 }
 /**//// 
 /// 得到父节点的SiteMapNode
 /// 
 /// 
 /// 
 private SiteMapNode GetParentNodeFromDataReader(DbDataReader reader)
 {
 if (reader.IsDBNull(_indexParent))
 throw new ProviderException("父节点不能是空");
 int pid = reader.GetInt32(_indexParent);
 if (!_nodes.ContainsKey(pid))
 throw new ProviderException("有重复节点ID");
 // 返回父节点的SiteMapNode
 return _nodes[pid];
 }
}
上面两个测试页面所需的web.config中的配置
 
 
 
 
 
 
 
 
 
 
 
 
 
[源码下载]
作者:webabcd