webabcd - 专注于asp.net, html5, silverlight

ASP.NET
从现在开始 一切都不晚
posts - 287, comments - 7866, trackbacks - 594, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理
[索引页]
[源码下载]



温故知新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
[源码下载]

Feedback

#1楼  回复 引用   

2007-02-15 00:01 by ivw[未注册用户]
沙发。。:)

#2楼  回复 引用 查看   

2007-02-15 07:50 by 张振      
关注这个系列

#3楼[楼主]  回复 引用 查看   

2007-02-15 08:55 by webabcd      
@ivw
兄弟不睡觉的吗?好精神!羡慕中……

@张振
:)
想赶快把这个写完,后面还有好多新的东西要学啊

#4楼  回复 引用   

2007-02-15 11:47 by ivw[未注册用户]
都习惯了12点后才睡了,早上8点起床上班。哎。真觉得累。

兄弟,知不知道读取硬盘序列号和CPU序列号除了wmi还有没有更好的办法啊?

#5楼  回复 引用 查看   

2007-02-15 13:53 by Cure      
@ivw
还可以用api

#6楼  回复 引用   

2007-02-15 14:33 by ivw[未注册用户]
有例子吗?应该可以在asp.net里运行吧?如果可以的话发到我的邮箱
liangivw@126.com
谢谢

#7楼  回复 引用   

2007-02-15 14:48 by ivw[未注册用户]
.......................,那有没有这方面的资料啊?

#8楼  回复 引用   

2007-02-15 15:31 by ivw[未注册用户]
http://www.cnblogs.com/singlepine/archive/2005/11/24/283664.html

这个是用API的,但得到的内容没有序列号。。

#9楼[楼主]  回复 引用 查看   

2007-05-20 12:00 by webabcd      
@ivw
偶尔发现,这里居然有我没回复的留言
sorry

看了你连接的那篇文章
序列号的是这个

public uint dwNumberOfProcessors;

#10楼  回复 引用   

2007-05-28 13:30 by 杨[未注册用户]
兄弟,数据库无法附加!

#11楼[楼主]  回复 引用 查看   

2007-05-28 15:03 by webabcd      
@杨
测试了一下,没问题啊

#12楼  回复 引用 查看   

2007-08-02 13:25 by 海鸥      
下载并安装后生成出错:

错误 102 未能加载类型“AttemptingToLogIntoLockedAccountEvent”。 E:\DynamicSiteMap\Web\Web.config

我是将其放在E:\DynamicSiteMap:下

还请指点!! 比较急,多谢!!!

#13楼[楼主]  回复 引用 查看   

2007-08-02 14:03 by webabcd      
@海鸥
不好意思,文件传错了,晚上回家后我会把正确的源代码传上来的

#14楼  回复 引用 查看   

2007-08-02 17:39 by 海鸥      
那就多谢了啊! 还有就是您写的那个:SqlSiteMapProvider.cs
有没有更多注释呢?或是更经典的。 比方说,可以按任意节点取得其
下面的所有子节点,以及动态控制取子节点的深度(个数)。
万分感谢!!

#15楼[楼主]  回复 引用 查看   

2007-08-03 07:54 by webabcd      
@海鸥
已经改好传上来了

SqlSiteMapProvider.cs是个provider,它的功能是在其基类中定义好的,并不能自己随便加功能的

#16楼  回复 引用   

2007-08-17 16:51 by 清风[未注册用户]
看上去挺不错,不过我看不太懂,还得慢慢研究

#17楼[楼主]  回复 引用 查看   

2007-08-17 18:52 by webabcd      
@清风
:)
嗯,作为站点地图来用还是非常好的

#18楼  回复 引用   

2007-08-20 11:06 by 清风[未注册用户]
SqlSiteMapProvider.cs这个看不太懂,可不可以多加点注释,呵呵!在加载第一个节点的时候运行有错误!!就是CreateSiteMapNodeFromDataReader这个方法下报错!

#19楼[楼主]  回复 引用 查看   

2007-08-20 11:41 by webabcd      
@清风
这个问题,其实关键的部分我都写上注释了,我觉得你最好先看看provider模式

然后再来看SqlSiteMapProvider

另外,兄弟可以先看一下ms官方的那些批批provider是怎么写的,我在源码里都有提供(其中包括XmlSiteMapProvider.cs)

xml的弄明白了,sql的自然也就明白了

#20楼  回复 引用   

2007-08-20 13:04 by 清风[未注册用户]
兄弟??呵呵,好的谢谢了

#21楼[楼主]  回复 引用 查看   

2007-08-20 13:31 by webabcd      
@清风
??MM??
呵,不好意思

不谢

#22楼  回复 引用   

2007-08-21 14:38 by 清风[未注册用户]
那个provider看不懂,太难了,有没有好材料或网址啊??呵呵

#23楼[楼主]  回复 引用 查看   

2007-08-21 18:49 by webabcd      
@清风
我当初学provider的时候,就是看源码然后一点一点弄懂的,这个不能太着急啊

我原来写过一个provider模式的示例
http://www.cnblogs.com/webabcd/archive/2007/01/22/626479.html

你可以参考一下

#24楼  回复 引用   

2007-08-22 08:50 by 清风[未注册用户]
真的很感谢啊!!下次有什么不懂在问你了,有机会请你吃饭,可是没机会,哈哈!!

#25楼[楼主]  回复 引用 查看   

2007-08-22 08:59 by webabcd      
@清风
好的
怎么能说没有机会
只要在地球上,那就有机会

我会记着,你欠我一顿饭的

#26楼  回复 引用   

2007-08-22 11:12 by 清风[未注册用户]
好啊!只请米饭没菜!!我终于知道Initialize(string name, NameValueCollection config)这个是干什么了看了半天才明白原来就是取config中的字符串连接啊,怎么这么麻烦啊,我以前在vb.net中用的很简单啊就一句话System.Configuration.ConfigurationSettings.AppSettings("ConnectionString")这样就取出来了啊!!!

#27楼[楼主]  回复 引用 查看   

2007-08-22 12:01 by webabcd      
@清风
:)
不是的
比如说membership的provider
<add name="SqlMembershipProvider"
type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
connectionStringName="SqlConnectionString"
enablePasswordRetrieval="false"
enablePasswordReset="true"
requiresQuestionAndAnswer="false"
applicationName="/"
requiresUniqueEmail="false"
passwordFormat="Hashed"
maxInvalidPasswordAttempts="3"
minRequiredPasswordLength="3"
minRequiredNonalphanumericCharacters="0"
passwordAttemptWindow="10"
passwordStrengthRegularExpression="" />

它还包含好多其他信息,Initialize(string name, NameValueCollection config)是要把他们都读出来的

#28楼  回复 引用   

2007-08-22 12:22 by 清风[未注册用户]
哦,不好意思,我以为就读"connectionStringName"这个东西了!!明白了

#29楼[楼主]  回复 引用 查看   

2007-08-22 12:45 by webabcd      
@清风
:)
这个模式还是挺有用的

#30楼  回复 引用   

2007-12-24 11:55 by 后进[未注册用户]
大哥,你的这个东西确实挺管用的 ,但是每次都是从数据库里面去加载数据,如果数据量太大的话,那不是要加载很久的时间哦!能不能实现生成一个静态的Web.SiteMap站点地图文件呢?

#31楼[楼主]  回复 引用 查看   

2007-12-24 12:21 by webabcd      
@后进
有牛人用SqlCacheDependency写过的
参考一下
http://msdn.microsoft.com/msdnmag/issues/06/02/wickedcode/default.aspx

#32楼  回复 引用   

2008-01-03 10:45 by 后进[未注册用户]
你说的那个地方,我去看了下,看不懂,你有做出来的吗?给我传一个行不行,我邮箱是 : baiping2@163.com 不胜感激!!!

#33楼[楼主]  回复 引用 查看   

2008-01-03 12:55 by webabcd      
@后进
他有做好的例子提供下载啊
http://download.microsoft.com/download/f/2/7/f279e71e-efb0-4155-873d-5554a0608523/WickedCode0602.exe

下下来直接用就好了

#34楼  回复 引用   

2008-01-04 16:08 by 后进[未注册用户]
还是不行啊 !跟我需要的不一样,我要的是读取数据库的直接生成一个Web.Sitemap的文件来覆盖原来的旧的文件,这样的话我就可以不用每次加载的是时候都从数据库里面去读,而不是每次使用的时候都要先从数据库里面去读一次。

#35楼  回复 引用   

2008-01-04 16:12 by 后进[未注册用户]
不行啊 ,你说的那个,它并没有 生成Web.Sitemap文件啊!还是每次使用的时候都要从数据库去加载,我的意思是要生成一个文件放在那里,当使用的时候就直接读取Web.Sitemap的的数据,而不从数据库加载,当我需要更新的时候在从数据库里面去加载

#36楼[楼主]  回复 引用 查看   

2008-01-04 16:58 by webabcd      
@后进
他用了SqlCacheDependency,不会每次都读数据库的

按你说的那实际上就是对xml的增删改操作了,这个跟对其它xml文件的操作没有区别

#37楼  回复 引用   

2008-01-07 09:01 by 后进[未注册用户]
@webabcd
那就如你说的对Web.Sitemap文件进行增删改操作,该怎么做呢?

#38楼[楼主]  回复 引用 查看   

2008-01-07 11:41 by webabcd      
@后进
就是和普通的xml的增删改操作一样,可以网上搜一下,有很多

#39楼  回复 引用   

2008-04-12 16:11 by dddd[未注册用户]
dddd我支持

#40楼[楼主]  回复 引用 查看   

2008-04-14 07:51 by webabcd      
@dddd
:)
多谢

#41楼  回复 引用   

2008-06-23 15:57 by starplayer[未注册用户]
请问,使用自定义站点地图提供程序来提供sitemap的数据,怎么样才能支持外部链接的地址? 我翻了很多资料都找不到,是不是站点地图节点的URL不支持外部链接,我试过了,都是提示安全性错误,不过用web.sitemap就不会出错.

#42楼[楼主]  回复 引用 查看   

2008-06-23 18:08 by webabcd      
@starplayer
确实,我试了一下,也是如此

msdn一下,google一下也没找到答案
有一个msdn提供的例子,兄弟可以试一下
http://msdn.microsoft.com/zh-cn/magazine/cc163657(en-us).aspx

#43楼  回复 引用   

2008-08-12 10:22 by 黄小舒[未注册用户]
前辈,请教你个问题:

SiteMap可以从数据库中读取,那可不可以传参数?

我是用SiteMap和TreeView来定制子菜单,根据主菜单传递的ID生成子菜单?

这有办法实现吗?

#44楼[楼主]  回复 引用 查看   

2008-08-12 18:35 by webabcd      
@黄小舒
这样的话,可以动态绑定TreeView啊

#45楼  回复 引用   

2008-08-22 10:16 by SmilingMoving[未注册用户]
请问下,sitemap中启用securityTrimmingEnabled,则父节点设置了roles属性,字节点在不设置roles的情况下默认与父节点有相同权限。有没有方法使得字节点不设置roles就没有访问权限?

#46楼[楼主]  回复 引用 查看   

2008-08-22 14:08 by webabcd      
@SmilingMoving
“有没有方法使得字节点不设置roles就没有访问权限?”
如果不给任何角色权限,那不就是不需要这个节点啦

#47楼  回复 引用   

2008-08-22 16:06 by SminigMoving[未注册用户]
谢谢lz的回复,我是想实现一个权限树的功能。管理员选择某角色可以访问哪些页面后,程序就去修改sitemap中对应页面的roles值。相当于是sitemap的每个节点都是独立的,子节点不会去共享父节点的设置的roles值,要是没设置角色就不许他人访问。可现在情况是,假设父节点设置了admin和user两个角色,它的子节点只设置了user角色,可现在admin用户也可以访问该子节点。

#48楼[楼主]  回复 引用 查看   

2008-08-22 18:39 by webabcd      
@SminigMoving
要管理员去配置角色的权限的话,可以这么做
数据库方式
http://msdn.microsoft.com/zh-cn/magazine/cc163657(en-us).aspx

修改web.config的方式
http://www.cnblogs.com/webabcd/archive/2007/06/10/778383.html

#49楼  回复 引用   

2008-09-27 17:28 by Savage[未注册用户]
请问LZ,出现这样的错误:
提供程序集合中不存在为 defaultProvider 指定的提供程序“XmlSiteMapProvider”。

是不是缺少什么引用啊?

#50楼[楼主]  回复 引用 查看   

2008-09-28 10:21 by webabcd      
@Savage
如果你的web.config里
指定了siteMap的defaultProvider属性
那么必须要有与其对应的provider的相关配置

#51楼  回复 引用 查看   

2008-10-29 16:26 by 问天何必      
留个足迹。。

#52楼[楼主]  回复 引用 查看   

2008-10-29 18:37 by webabcd      
@问天何必
:)
呵呵
确实,用不到的可以暂先不看,等用到时或者想学的时候能找到学习资源就好

#53楼  回复 引用   

2008-10-30 13:18 by 不错[未注册用户]
正在烦treeview和sitemappath并用读数据库
好使啊,用泛型保存节点,不用递进整个树,算法很巧,谢谢了

#54楼[楼主]  回复 引用 查看   

2008-10-30 18:25 by webabcd      
@不错
:)
过奖了,不谢

#55楼  回复 引用   

2008-10-30 19:20 by 不错[未注册用户]
发现一个问题,更新了数据 库,不会反映出来,大大有什么好的办法

#56楼[楼主]  回复 引用 查看   

2008-10-31 07:42 by webabcd      
@不错
不会啊
跟一下,看看读取的数据源对不对

#57楼  回复 引用   

2008-10-31 11:59 by 不知所错[未注册用户]
第一次可以读取数据,第二修取了数据库的节点内容,就不更新了,我断点跟踪,发现这里
// 单例模式的实现
if (node != null)
{
return node;
}
这里,第一次加载了根节点的信息,已经存在不再调用sqlreader读第二次更新的数据了。 webabcd你看看是不是有这样的情况

#58楼[楼主]  回复 引用 查看   

2008-10-31 13:21 by webabcd      
@不知所错
不会啊
我用我的demo测试了一下,修改了数据库的数据是可以获取到的

另外纠正我的一个错误,原来写的是“// 单例模式的实现”,可能是当时脑袋进水了,那部分应该是为了线程安全才写的代码,因为可能会有并发问题

#59楼  回复 引用   

2008-10-31 20:10 by 不知所错[未注册用户]
也许吧
我用的是sql2000,打不开的你数库,可不可以转成2000的格式放上来参考一下
装了express2005又不会用

#60楼[楼主]  回复 引用 查看   

2008-11-03 07:38 by webabcd      
@不知所错
没有啊
不过,应该尽快升级到至少2005,比2000强很多啊

#61楼  回复 引用   

2009-04-20 09:43 by 迷茫的小菜[未注册用户]
Server Error in '/VS2005' Application.
--------------------------------------------------------------------------------

Configuration Error
Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

Parser Error Message: An error occurred loading a configuration file: Failed to start monitoring changes to 'C:\Documents and Settings\studio\桌面\VS2005' because access is denied.

Source Error:


[No relevant source lines]


这是什么问题呢?大哥

#62楼[楼主]  回复 引用 查看   

2009-04-20 11:45 by webabcd      
@迷茫的小菜
没权限加载配置文件
别在桌面上执行,比如放到c:\试试

#63楼  回复 引用   

2009-04-21 10:12 by 迷茫的小菜[未注册用户]
@webabcd
LZ,还是不行吖..把权限都改成完全控制了还不行..可能是IIS的问题..
另外请教下LZ.你是怎么学的呢?能不能割爱传授下学习心法...个人感觉自己的学习方法不是很好..学过就忘..很难往深层走..望LZ不吝赐教.
谢了..
Email:skinsen@foxmail.com

#64楼[楼主]  回复 引用 查看   

2009-04-21 11:21 by webabcd      
@迷茫的小菜
嗯。。。也许

学习的话,就是一个一个地做例子,没什么特别的,如果平时不经常用的话,肯定容易忘,只要用到的时候,能快速高质量地重新拿起来就好

#65楼  回复 引用   

2009-08-31 09:39 by lanse[未注册用户]
非常好的例子!

#66楼  回复 引用   

2009-08-31 09:41 by apple_love[未注册用户]
引用lanse:非常好的例子!

#67楼  回复 引用   

2009-08-31 09:42 by fengshan[未注册用户]
引用apple_love:
引用lanse:非常好的例子!


#68楼[楼主]  回复 引用 查看   

2009-08-31 12:19 by webabcd      
@fengshan
@apple_love
@lanse
???
测试呢
???

#69楼  回复 引用 查看   

2009-11-25 17:05 by cnbycnby      
今天 ,读了你的文章 对sitemapt 有了 更多认识 , 我自己 也做了一个, 用的是自己 的数据 库, 主要是 想 实现 站点地图(从数据库读数据),模访了 你的 SqlSiteMapProvider 类, 出了各种 错误 , 现在 还 有个没有解决 ,
如下:
System.ArgumentException: 已添加了具有相同键的项。
在 System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
在 System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
在 System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
在 SqlSiteMapProvider.CreateSiteMapNodeFromDataReader(DbDataReader reader) 位置 f:\完成项目\Eshop权限管理\ESHOP\ESHOP\WEB\App_Code\SqlSiteMapProvider.cs:行号 183
在 SqlSiteMapProvider.BuildSiteMap() 位置 f:\完成项目\Eshop权限管理\ESHOP\ESHOP\WEB\App_Code\SqlSiteMapProvider.cs:行号 117



是不是 我数据 库的问题, 我的id 是自增长的啊, 没有重复,

请 帮忙 解决 ,
方便 联系QQ 1021155699 ,先谢谢了

#70楼[楼主]  回复 引用 查看   

2009-11-26 08:18 by webabcd      
@cnbycnby
调用这个方法的时候出错
private SiteMapNode CreateSiteMapNodeFromDataReader(DbDataReader reader)
跟进去看看,往SiteMapNode里添加的时候出现重复id

#71楼  回复 引用 查看   

2009-11-26 11:56 by cnbycnby      
呵呵 ,上个问题解决 了啊 , 可是 又有个新 问题, 就是 读出来 数据,我 数据 库里 已经 修改了, 而页面 上怎么刷新 都 还是老的数据 , 把 页面 关了 ,再开 还是老样子, 是不是 有缓存 啊 ???

#72楼[楼主]  回复 引用 查看   

2009-11-27 08:32 by webabcd      
@cnbycnby
调试程序,跟踪对应的代码的执行状况,就能查出原因了

#73楼  回复 引用 查看   

2009-11-27 09:32 by cnbycnby      
呵呵 , 对你的 做了点小小的改造, 现在 可以 生成 sitemap 文件了(楼上也有朋友说想要的 ), 原理 很简单的, 也贴 出来 给大家看看吧,
楼主不要见笑 啊,只改造下 BuildSiteMap() 就行了, 呵呵 !
public override SiteMapNode BuildSiteMap()
{

lock (_lock)
{
// 线程安全的实现
if (_node != null)
return _node;
//////////////
xmldoc = new XmlDocument();
//加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?>
XmlDeclaration xmldecl;
xmldecl = xmldoc.CreateXmlDeclaration("1.0", "gb2312", null);
xmldoc.AppendChild(xmldecl);
//加入一个根元素
xmlelem = xmldoc.CreateElement("","siteMap","");


xmldoc.AppendChild(xmlelem);

////////////////

SqlConnection connection = new SqlConnection(SqlHelper.connectionString );

try
{
SqlCommand command = new SqlCommand(SqlString.GetSitMap, connection);
command.CommandType = CommandType.StoredProcedure;

connection.Open();
SqlDataReader reader = command.ExecuteReader();

// 获得各个字段的索引
_indexID = reader.GetOrdinal("Module_id");
_indexUrl = reader.GetOrdinal("Module_Url");
_indexTitle = reader.GetOrdinal("Module_Name");
_indexDesc = reader.GetOrdinal("Descrip");
_indexParent = reader.GetOrdinal("Module_Parentid");
if (reader.Read())
{
// 把第一条记录作为根节点添加
_node = CreateSiteMapNodeFromDataReader(reader);
AddNode(_node, null);
// 查找 sitemap 节点
XmlNode root = xmldoc.SelectSingleNode("siteMap");
XmlElement xe = xmldoc.CreateElement("siteMapNode");
xe.SetAttribute("url", _node.Url);
xe.SetAttribute("title", _node.Title);
xe.SetAttribute("description", _node.Description);
root.AppendChild(xe);


// 构造节点树
while (reader.Read())
{
// 在站点地图中增加一个节点
SiteMapNode node = CreateSiteMapNodeFromDataReader(reader);
AddNode(node, GetParentNodeFromDataReader(reader));

XmlElement xe1 = xmldoc.CreateElement("siteMapNode");
xe1.SetAttribute("url", node.Url);
xe1.SetAttribute("title", node.Title);
xe1.SetAttribute("description", node.Description);


root.AppendChild(xe1);

}

}


xmldoc.Save(HttpContext .Current.Server.MapPath("data.xml"));
reader.Close();
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
finally
{
connection.Close();
xmldoc.Save("data.xml");
}

// 返回SiteMapNode
return _node;
}

}

#74楼[楼主]  回复 引用 查看   

2009-11-27 11:55 by webabcd      
@cnbycnby
:)
不错

#75楼  回复 引用 查看   

2010-01-29 12:41 by KissFly      
SiteMapProvider="XmlSiteMapProviderTest"
请教下楼主, XmlSiteMapProviderTest是哪个文件?

#76楼[楼主]  回复 引用 查看   

2010-01-29 17:42 by webabcd      
@KissFly
是在这里配置的
<add name="XmlSiteMapProviderTest" type="System.Web.XmlSiteMapProvider, System.Web, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" siteMapFile="~/Sitemap/Web.sitemap"/>
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 650773 RrHYpKbHTIE=