温故知新ASP.NET 2.0(C#)(3) - SiteMap(站点地图)

[索引页]
[源码下载]


温故知新ASP.NET 2.0(C#)(3) - SiteMap(站点地图)


作者:webabcd


介绍
ASP.NET 2.0 中的站点导航提供程序向应用程序中的页公开导航信息,使您可以独立于页的实际物理布局定义站点的结构。默认站点导航提供程序基于XML,但通过为站点地图编写自定义提供程序,也可以从任意后端公开此信息。


关键
1、创建.sitemap文件,其实就是一个xml文件,包括有着层次结构的<siteMapNode>元素

2、<siteMapNode>元素的属性:
  Url - 链接地址
  Title - 显示的标题
  Description - 描述(ToolTip)
  resourceKey - 本地化用的(要在<siteMap>节点加上这个属性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属性的节点)
<? xml version ="1.0" encoding ="utf-8" ?>
< siteMap xmlns ="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
     < siteMapNode url ="~/SiteMap/Test.aspx#1" title ="首页"     description ="首页描述" >
         < siteMapNode url ="~/SiteMap/Test.aspx#2" title ="频道1"     description ="频道1描述" />
         < siteMapNode url ="~/SiteMap/Test.aspx#3" title ="频道2" description ="频道2描述" />
         < siteMapNode siteMapFile ="WebChild.sitemap" >
         </ siteMapNode >
         < siteMapNode url ="~/SiteMap/Test.aspx#4" title ="频道4" description ="频道4描述" />
     </ siteMapNode >
</ siteMap >
 
SiteMap/WebChild.sitemap(上面.sitemap文件某个节点的siteMapFile属性所指定的文件)
<? xml version ="1.0" encoding ="utf-8" ?>
< siteMap xmlns ="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
     < siteMapNode url ="~/SiteMap/Test.aspx#5" title ="频道3"     description ="频道3" >
         < siteMapNode url ="~/SiteMap/Test.aspx#6" title ="栏目1"     description ="栏目1描述" />
         < siteMapNode url ="~/SiteMap/Test.aspx#7" title ="栏目2"     description ="栏目2描述" />
         < siteMapNode url ="~/SiteMap/Test.aspx#8" title ="栏目3"     description ="栏目3描述" />
     </ siteMapNode >
</ siteMap >
 
 
站点地图测试
SiteMap/Test.aspx
<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Test.aspx.cs"
        Inherits="SiteMap_Test" Title="站点地图测试" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
        <p>
                <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1">
                </asp:TreeView>
                <asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource2" Orientation="Horizontal">
                </asp:Menu>
                <%--显示根节点的数据源--%>
                <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" SiteMapProvider="XmlSiteMapProviderTest" />
                <%--不显示根节点的数据源--%>
                <asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server" SiteMapProvider="XmlSiteMapProviderTest"
                        ShowStartingNode="false" />
        </p>
        <p>
                编码方式访问节点信息如下<br />
                <asp:Label ID="lbl" runat="server" BackColor="#DDDDDD" />
        </p>
</asp:Content>
 
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 + "<br />";

                 // 取得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="站点地图测试(从数据库读数据)" %>

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
        <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1">
        </asp:TreeView>
        <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" SiteMapProvider="SqlSiteMapProvider" />
</asp:Content>
 
自定义站点地图提供程序(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;

/// <summary>
/// SqlSiteMapProvider
/// </summary>
public class SqlSiteMapProvider : StaticSiteMapProvider
{
         private string _strCon;
         private int _indexID, _indexTitle, _indexUrl, _indexDesc, _indexParent;

         // 节点
         private SiteMapNode _node;
        
         // 节点字典表
         private Dictionary< int, SiteMapNode> _nodes = new Dictionary< int, SiteMapNode>();
        
         // for 线程安全
         private readonly object _lock = new object();

         /// <summary>
         /// 初始化
         /// </summary>
         /// <param name="name">name</param>
         /// <param name="config">config</param>
         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( "连接字符串是空的");
        }

         /// <summary>
         /// 从持久性存储区加载站点地图信息,并在内存中构建它
         /// </summary>
         /// <returns></returns>
         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;
                }
        }

         /// <summary>
         /// 将检索目前由当前提供程序管理的所有节点的根节点
         /// </summary>
         /// <returns></returns>
         protected override SiteMapNode GetRootNodeCore()
        {
                 lock (_lock)
                {
                         return BuildSiteMap();
                }
        }

         /// <summary>
         /// 根据DataReader读出来的数据返回SiteMapNode
         /// </summary>
         /// <param name="reader">DbDataReader</param>
         /// <returns></returns>
         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;
        }

         /// <summary>
         /// 得到父节点的SiteMapNode
         /// </summary>
         /// <param name="reader"></param>
         /// <returns></returns>
         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中的配置
<configuration>
    <appSettings/>
    <connectionStrings>
        <add name="SqlConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Database.mdf;Integrated Security=True;User Instance=True"/>
    </connectionStrings>
    <system.web>
        <siteMap enabled="true" defaultProvider="XmlSiteMapProvider">
            <providers>
                <add name="XmlSiteMapProvider" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="~/Web.sitemap"/>
                <add name="XmlSiteMapProviderTest" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="~/Sitemap/Web.sitemap"/>
                <add name="SqlSiteMapProvider" type="SqlSiteMapProvider" connectionStringName="SqlConnectionString" />
            </providers>
        </siteMap>
    </system.web>
</configuration>
 
OK
[源码下载]
 

你可能感兴趣的:(net,asp,Sitemap,站点,温故知新)