传统的URL的形式如同:
http://www.dotnetnuke.com/default.aspx?tabid=510&Name=Pm2004
页面通过parameter=value的形式给页面传递参数,页面根据参数加载不同的内容。但是,DNN因为以下原因放弃了传统的形式:
(1) 这种方式不利于阅读和人们的理解。不够人性化。
(2) 很多搜索引擎会忽略,搜索引擎会避免参数。不利于网络搜索。
(1) 有利于搜索引擎发现
(2) 有利于人们阅读
(3) 适合child portal
(4) 不影响其它应用
(5) 性能
DNN的解决方案类似于翻译员,将一种语言翻译成另外的一种语言。最终的本质还是带有参数的形式,只是在表现上,在URL的字符串中出现的是Friendly的。这里用到的一个术语是URL Schema的规则集。通过这组规则完成原生URL和Friendly URL之间的相互翻译。
如:
原始的URL是:
http://www.dotnetnuke.com/default.aspx?tabid=703
被翻译为:
http://www.dotnetnuke.com/tabid/703/default.aspx
URL Schema将一种表达方式转化为另一种表达方式,这种结果是确定的,而且是唯一的。这是我们谈到的一种情况,就是请求URL的转换方式。HTTP还包含一种响应模式,我们的机制同时要满足这样的要求,例如用户可能希望看到新闻组的网页在浏览器中显示的是:
http://www.dotnetnuke.com/About/News.aspx,
而不是:
http://www.dotnetnuke.com/About/News/tabid/703/Default.aspx
在SiteUrls.config文件中定义了相应的规则:
结合对源码的分析,这里的规则是全匹配,而不是局部的匹配。同时利用正则表达式Match Groups属性,将匹配的Value取出,并填入SendTo中,如$1。
在Web.Config中定义了:
在HTTP请求中,IIS允许开发者在HTTP请求的管道中插入若干Module来处理加工/处理该请求。Module像在管道中的一个截面,流经这个截面的信息都被Module处理一下。
在URLRewriteModule中 Init 只是定义了一个事件而已
AddHandler application.BeginRequest, AddressOf Me.OnBeginRequest
在OnBeginRequest中处理的过程比较复杂,这个方法中包含了一些基本的URL转换规则定义,另外的一部分在SiteUrls.Config中以URL Schema的形式进行了定义。
基本的步骤是:
在网站的开发中,我们经常需要跳转,从一个页面转入另外的页面,虽然我们理解了DNN Friendly Url的基本思想,但是在实战中,我们拼凑一个这样的URL还是很费力的,为此DNN提供了几个辅助类和相应的方法。下面我们介绍这些方法和类,并且给出一些应用。
沿袭ASP.NET2/DNN的一贯思想,使用Provider的机制来灵活定制程序的运行方式,Friendly Url也是采用这种方式,在Web.Config中定义了:
它实现了
等方法。
我们考查一下下面这个函数
其中Tab其实就是DNN portal每个菜单(或者页面);
Path就是路径,可能是~开头的相对路径,也可能是绝对路径,可能是/也可能是\。如果有参数(&?形式的参数)就包含在这个字符串中。
PageName是页面文件,比如default.aspx,这个页面会替换掉Path中的页面。
Setting主要是为了取出Portal的根路径或者Alias路径
通过这些参数能够组合,格式化成一个Friendly Url。注意最后形成的Friendly URL中可能也含有参数,目前regexMatch="[^a-zA-Z0-9 _-]这些参数才可以被Friendly化。
翻阅DNN的代码,经常会碰到使用EditURL函数,比如,最常见的我们在可以编辑的Item前面有一支笔,点击后就跳到编辑的页面:
<asp:HyperLink NavigateUrl='<%# EditURL("ItemID",DataBinder.Eval(Container.DataItem,"ItemID")) %>' Visible="<%# IsEditable %>" runat="server" ID="Hyperlink1"><asp:Image ID=Hyperlink1Image Runat=server ImageUrl="~/images/edit.gif" AlternateText="Edit" Visible="<%#IsEditable%>" resourcekey="Edit"/></asp:hyperlink>
EditURL主要是为了跳转到Edit页面而定义的,当然它也可以跳转到其他Control页面。它在模块的基类PortalModuleBase中被定义。它被重载了5次,可以什么参数都不带,也可以Public Function EditUrl(ByVal KeyName As String, ByVal KeyValue As String, ByVal ControlKey As String, ByVal ParamArray AdditionalParameters As String()) As String
它处在模块的基类中,很方便使用,也是出镜率很高的函数之一。
它调用Global.vb中NavigateURL函数,这是一个Static函数。NavigateURL调用Global.vb中的FriendlyUrl函数,该函数按照Provider的机制加载相应的DNNFriendlyUrlProvider
DotNetNuke.Services.Url.FriendlyUrl.FriendlyUrlProvider.Instance().FriendlyUrl(tab, path, pageName, portalAlias)
在DNN 的开发过程中,经常需要跳转页面,下面就不同的场合下给出解决的对策(以下描述的主要是目标URL串如何生成):
(1) 在模块定义中定义了两个或多个Control,需要从一个Control页面跳到另一个页面。
同一个模块,不同Control之间的跳动,而且不涉及参数的传递,使用EditUrl(ControlKey)
(2) 上述的情况,在很多情况下我们需要传入一些参数,特别是ItemID,在接收的模块中会提取此参数进行判断。比如在Blog模块中:
定义了View_Entry Control,可能需要从View Blog中跳转,就可以用EditUrl(“ItemID”,”
同一个模块,不同Control之间的跳动,而且涉及某一个参数的传递,可以使用
EditUrl(KeyName, KeyValue, ControlKey),如果是Edit Control可以省略为
EditUrl(KeyName, KeyValue)
(3) 在有的时候我们可能需要传递更多的参数,我们使用EditUrl(KeyName, ByVal KeyValue, ControlKey, ByVal ParamArray AdditionalParameters As String())
最后的参数是可以被罗列的,比如
EditUrl(“CaterogyCode”,”
它的含义是,跳转到ViewDetail Control页面里,其中CaterogyCode=123,StoreID=431等等。
(4) 如果我们希望在不同的Tab中进行跳转,比如我跳转到首页,或者已知的某个TabID的页面可以NavigateURL(ByVal TabID As Integer)
以下代码帮助跳转到"产品"页:
(5) 最为灵活的
Public Function NavigateURL(ByVal TabID As Integer, ByVal IsSuperTab As Boolean, ByVal settings As PortalSettings, ByVal ControlKey As String, ByVal ParamArray AdditionalParameters As String()) As String
函数,借助它能够带上ControlKey以及N多的额外参数。
总结上面两个函数:
在同一个模块不同Control之间跳转,可以使用EditUrl。
在不同Tab之间跳转使用NavigateUrl。
他们都可以传递若干参数。
这两个函数都是没有办法改变最终的aspx文件名的,但是Globals.vb中定义的FriendlyUrl可以实现Path的自定义,更换*.aspx等等。具有更大的灵活性,但是使用不多见。