随心所欲

做个幸福的人
posts - 147, comments - 1402, trackbacks - 28, articles - 0
  博客园 :: 首页 :: 新随笔 ::  :: 订阅 订阅 :: 管理
SiteMap,网站地图,在网站建设的时候是很有用的。它可以直接绑定在Men和TreeView控件上,还有一个指示当前路径的SiteMapPath控件,也可以直接绑定。
这是他常用的xml定义:
 
<siteMapNode url="Course/Group/GroupList.aspx" title="GroupAdmin" >

这个SiteMap的权限已经和Membership结合起来了,不同权限的用户所看到的地图已经被控制了。可以配置role属性来扩展例外的访问许可。注意,是例外的访问许可。
<siteMapNode url="Course/Tests/TestList.aspx" title="TestAdmin" role="student">
这里有些介绍:http://zmsx.cnblogs.com/archive/2006/01/03/310381.aspx

简单的使用这里不作赘述,只是讨论一下怎么和扩展一下,让他可以访问资源时附带参数。

首先介绍这样一个资源:MySiteMapTool:http://quitgame.cnblogs.com/archive/2005/11/24/283910.aspx
这位仁兄已经提供了一个工具,可以在程序中转发带参数的请求
比如:
MySiteMap.Forward("Details""AlbumID={0}&Page={1}"14); 

确是简单实用。

现在想要的功能是:因为各个液面都需要不同的参数,所以在没有这些参数的情况下就禁止用户访问那个页面,转而访问父一级页面,递归。

首先,SiteMap本身有个SiteMapResolve事件,在当前路径被解析时触发,这是一段来自MSDN的代码


这段代码只是给当前路径加载参数。

曾经尝试过使用类似的方法,但是SiteMapPath搞定了,Menu就绑定不上数据了。并且只能处理一部分数据。


后来,结合SiteMapTool那个类,又写出几个函数可以解决这个问题
这是修改之后的sitemap文件,加了一个配置项:rule,里面的参数是这个页面需要的参数。如果当前上下文没有这些参数,那么禁止用户访问这个页面。

<siteMapNode url="Course/Group/GroupDetail.aspx" title="Group Detail" rule="cid;gid">

这是两个函数,递归处理所有的路径。
  private string MakeURL(SiteMapNode node)
    
{
        node.ReadOnly 
= false;
        
//find the static url 
        string url = MySiteMap.FindForward(node.Title);
        
if (node["rule"!= null && node["rule"].Length > 0)
        
{
            
//if have the rule,then check
            string[] paramSet = node["rule"].Split(';');
            
//check
            for (int i = 0; i < paramSet.Length; i++)
            
{
                
//if request have not such a param, then invoke self to check his parent
                if (HttpContext.Current.Request.Params[paramSet[i]] == null)
                    
return MakeURL(node.ParentNode);
            }

            
//if pass ,then add all the params and return the value
            url += "?";
            
for (int i = 0; i < paramSet.Length; i++)
            
{
                
string key = paramSet[i];
                
//'cid'--->'cid=1'. the former format is like : rule='cid;tid'
                url = url + key + "=" + HttpContext.Current.Request.Params[key] + "&";
            }

            
return url.Substring(0, url.Length - 1); //remove last '&'

        }

        
else
        
{
            
//if there is no rule then return the url directly
            return url;
        }

    }
    private void ReBindData(SiteMapNode root)
    
{
        
string url = MakeURL(root);
        
if (url != "")
            root.Url 
= url;
        
for (int i = 0; i < root.ChildNodes.Count; i++)
        
{
            ReBindData(root.ChildNodes[i]);
        }

    }
在ReBindData里面递归调用MakeUrl函数。
MakeUrl函数里面调用的MySiteMap.FindForward函数就是来自那位http://quitgame.cnblogs.com/archive/2005/11/24/283910.aspx的实现。
不过应用的是后需要做一些改动:他原来的实现是用静态的类如此加载
        //SiteMapNodeCollection smc = SiteMap.RootNode.GetAllNodes();
        
//siteMapCol = new NameValueCollection();

        
//IEnumerator ie = smc.GetEnumerator();
        
//while (ie.MoveNext())
        
//{
        
//    siteMapCol[((SiteMapNode)ie.Current).Title] = ((SiteMapNode)ie.Current).Url;
        
//}
但是,由于用户在没有登陆的时候,限于权限,它能访问的页面有限,所以SiteMap.RootNode.GetAllNodes();得到的不是所有数据,可能只是一部分或者0。
改动方式就是自己写一个函数,直接读取xml文件,递归获取所有数据定义。

Feedback

#1楼    回复  引用    

2007-07-03 14:52 by welland [未注册用户]
怎么调用呢?

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

2007-07-11 10:18 by 随心所欲      
@welland
调用什么呢?也就是读取数据吧,或者设置可用不可用。

#3楼    回复  引用  查看    

2007-07-17 15:09 by 一抹微蓝      
我的意思是怎么使用这些代码

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

2007-07-17 15:20 by 随心所欲      
@一抹微蓝
这要看sitemap是放置在masterpage上的还是放置在其他页面的。
如果放在masterpage上,Rebind函数就可以在MasterPage里面执行,在每次的身份或者页面切换的时候进行检查。
如果是放置在普通page上,自然是在页面上执行了。我一般都是定义一个BasePage:Page,这样我就可以把实现写到BasePage里面,让所有aspx继承就可以了。




标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2006-07-12 11:21 编辑过
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接:
 
Google