在前面文章里说明了DNN的架构,下面这个图应该说是更加能够全面的让你去了解它的结构:
如果你是个asp.net新手建议你看看前面这部分,因为它会向你介绍什么是http module,以及其他的一些概念。我想通过你读这篇文章来明白asp.net的机制,明白一些深层次的东西。我试着让大家我写的东西时不仅仅是跟着我去做某件事,而是了解了它。甚至去了解为什么要去做这件事。 废话太多了。。。
在进入主题http module之前需要你先了解几个概念,HTTP Pipeline.维基百科上对它的解释如下:
HTTP pipelining is a technique in which multiple HTTP requests are written out to a single socket without waiting for the corresponding responses. Pipelining is only supported in HTTP/1.1, not in 1.0.
The pipelining of requests results in a dramatic improvement[citation needed] in page loading times, especially over high latency connections such as satellite Internet connections.
Since it is usually possible to fit several HTTP requests in the same TCP packet, HTTP pipelining allows fewer TCP packets to be sent over the network, reducing network load.
Non-idempotent methods like POST should not be pipelined. Sequences of GET and HEAD requests can be always pipelined. A sequence of other idempotent requests like GET, HEAD, PUT and DELETE can be pipelined or not depending on whether requests in the sequence depend on the effect of others.[1]
HTTP pipelining requires both the client and the server to support it. HTTP/1.1 conforming servers are required to support pipelining. This does not mean that servers are required to pipeline responses, but that they are required not to fail if a client chooses to pipeline requests.
http://en.wikipedia.org/wiki/HTTP_pipelining
说白了就是不需要等待服务器的回应向服务器发送多个http请求,它大大降低了页面的加载时间。
Asp.net 提供了好几种方式来实现http pipeline。其中用的比较广泛的就是我们这里所说的http Module,一种用户自定义组件方式。
如果你英文好点建议你看如下这个链接来了解下HTTP Pipeline和http module,
http://msdn.microsoft.com/en-us/magazine/cc301362.aspx
http://msdn.microsoft.com/en-us/library/ms178473(v=VS.80).aspx
如果想看着舒服点的中文建议你看如下这位大哥写的介绍http请求处理流程的文章:
http://en.wikipedia.org/wiki/HTTP_pipelining
Http Handler的介绍:
http://www.tracefact.net/Asp-Net-Architecture/Introduction-to-Http-Handler.aspx
以及HTTP Module的介绍:
http://www.tracefact.net/Asp-Net/Introduction-to-Http-Module.aspx
里面包含了很多例子。你可以边看边学。而且讲得也非常好。
如果你认真看完了上面的内容我相信你已经了解了HTTP Module的作用。你也会了解了.net的项目中Global.asax是干嘛的了。大致的请求流程如下图:
DNN 中HTTP Modules的演变和HTTP Module的事件
现在我们来看DNN的源代码有一部分叫做Http Modules。
其实DNN之前的版本也是把http modules都放在了global.asax.vb里面(因为之前都是vb版本)。后来把这些模块给放到http module单独这个模块了。原因如下:
- 管理员可以在系统中添加/移除这些模块,因为本身是个module。
- 开发人员可以能够在不修改主程序也就是DNN.liabrary的情况下可以修改或者替换这些HTTP modules。
- 给大家提供了一个扩展HTTP Pipeline的模板。因为你可以自己加上自己的HTTP Module
上面我提供的参考文章里也有介绍.net framework自带的一些http module都在.net framewrok下有个config文件里放着,我们扩展后的HTTP Module也需要在
DNN的web.config中配置:
我们知道HTTP Module都是继承了IhttpModule这个接口。
在Init方法中我们为context的某个事件来个委托。
HTTP Module的事件分为三种
- 应用程序执行之前发生。
主要有:
BeginRequest:每次程序向服务器发送请求它都会被触发。
AuthenticateRequest: 表示请求准备好服务器端的认证,认证模式下使用
AuthorizeRequest: 表示请求准备好服务器端授权。
ResolveRequestCache: 在Output Cache模块中通过使用缓存让请求更短。
AcquireReuqestState: 表示能获得请求前的状态。
PreRequesthandlerExecute: 在程序的http请求发生前你可以触发的最后一个事件。
应用程序执行之后发生:
PostRequestHandlerExecute:此事件在执行 HTTP 处理程序之后发生。 ReleaseRequestState:将会话状态重新存储在状态存储中。如果您要构建一个自定义
会话状态模块,则必须将您的状态重新存储在状态存储中。
UpdateRequestCache:此事件将输出重新写入输出缓存。如果您要构建自定义缓存模块,则可以将输出重新写入缓存中。
EndRequest:请求已完成。您可能希望构建一个调试模块,以便将整个请求的信息收集到一起,然后将信息写入页面中。
DNN中的URL Writer HTTP Module详细介绍
URL重写是一个好的系统必须具备的。DNN的URL重写也是给大家提供了很多种URL重写的格式,归根到底也是为了URL的友好型,以及有利于SEO。下面这个就是DNN的一个友好的URL:
http://www.dotnetnuke.com/RoadMap/FriendlyURLs/tabid/622/default.aspx
如果你对URL的友好型不了解请直接Google下或者是请假下别人,这里不再罗嗦。
URL重写实在HTTP Pipeline的请求进行时发生的,所以能够作为整个应用程序的事件。这里用到的HTTP Module事件是BeginRequest。也就是说每次一个页面
向服务器发送HTTP Handler请求前通过BeginRequest事件让服务器相信你的url是接下来请求的那个页面的。
这种转换过程借助于SiteUrls.config文件中的正则表达式来完成。
<RewriterConfig>
<Rules>
<RewriterRule>
<LookFor>.*/TabId/(\d+)(.*)/Logoff.aspx</LookFor>
<SendTo>∼/Admin/Security/Logoff.aspx?tabid=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>.*/TabId/(\d+)(.*)/rss.aspx</LookFor>
<SendTo>∼/rss.aspx?TabId=$1</SendTo>
</RewriterRule>
<RewriterRule>
<LookFor>[ ˆ ?]*/TabId/(\d+)(.*)</LookFor>
<SendTo>∼/Default.aspx?TabId=$1</SendTo>
</RewriterRule>
</Rules>
</RewriterConfig>
可以看到里面的节点主要是LookFor和SendTo。没错。也就是说当程序发现URL是…tabid/622/rss.aspx时它就会去找到rrs.aspx?Tabid=622来获取内容。
后面的url是代码所能是别的url。
相同的道理如果url是
http://localhost/dotnetnuke_community_cs/tabid/21/portalid/0/Default.aspx 那么实际上的url是default.aspx?tabid=21。
当然你如果喜欢你可以强制性的去把某个url绝对比配,不使用正则表达式。
<LookFor>.*/XXOO/Url.aspx</LookFor>
<SendTo>∼/default.aspx?tabid=622</SendTo>
</RewriterRule>
接下来我们分析下上面给出的基本的DNN url:
http://www.dotnetnuke.com/RoadMap/FriendlyURLs/tabid/622/default.aspx
http://www.dotnetnuke.com --- 是整个网站的url
RoadMap/FriendlyURLS---是导航菜单的名字。也就是1级菜单的名字。你可以到DNN官网上试试。
Tabid/622/ ---是真实的url中的参数(?tabid=622)
Default.aspx --- DNN中最重要那个页面吧。。。
当然了那个导航菜单是否需要显示在url中你可以通过web.config文件中friendlyurl部分来设定。可能对于一个小的网站你在主网站下不需要再分类了,
比如不需要分什么product, community等。
DNN这种URL重写的方式最大的优点不需要从服务器查找数据来进行url的重写准备,而是使用正则表达式。我见过很多网站的URL重写时需要不停地
和数据库交互,对于大的网站这个很影响性能的。
上面这个URL格式是对于SEO有好处的,但是很多时候大家希望有一个容易记住的url也就是传说中的人性化。但是这个只适合小型网站,你就硬写入
上面那个配置文件中。DNN5也有一个配置能够让URL成为人类友好型的那种。这里不说了。
DNN的URL重写也使用了Provider Module模式,别于大家去扩展它的URL重写。不得不佩服它的扩展性,无处不在啊。。。
上面既然说它扩展性好,如何去写一个自己的URL重写provider呢?
首先你需要创建一个Provider类是继承下面这个类的:
然后你在这些方法里面写入自己公司的url 从写规则。具体的我会在后面文章里给出例子。写完这个编译后,你只需要在web.config中把你的
provider加进来就可以了。
<providers>
<clear />
<add name="DNNFriendlyUrl"
type="DotNetNuke.Services.Url.FriendlyUrl.DNNFriendlyUrlProvider,
DotNetNuke.HttpModules.UrlRewrite" includePageName="true"
regexMatch="[ ˆ a-zA-Z0-9 _-]"/>
<add name="CustomFriendlyUrl"
type="CompanyName.FriendlyUrlProvider, CompanyName.FriendlyUrlProvider" />
</providers>
</friendlyUrl>
上面只是粗略的说明了下DNN的url重写是如何进行的。代码级别的研究以及自定义url 规则都会单独有文章来介绍。
PS:DNN的URL重写你如果掌握了,你完全可以把它移植出来到你的项目中。
DNN的Exception HTTP Module模块
上面url重写部分使用的是BeginRequest事件,而Exception模块我们需要在整个应用程序发生错误时就去执行某个方法。代码如下:
也同时会把这个异常信息存储到数据库中来供开发人员分析。
DNN的UserOnline HTTP Module
这个Module监听的是AuthorizeRequest事件。每当一个用户向服务器端发出身份认证时这个HTTP Module就会向服务器发送请求,useronlineprovider就会执行。
DNN的usernolineprovider主要是使用Cookie来存放唯一标识的。这样可以防止那些在线的游客被重复记录。当然了这个功能主要是靠DNN的Scheduler模块
在后台有个线程没几分钟去执行下。
DNN UserOnline模块的代码级别研究也会在以后一篇文章里介绍。这里你知道原理就行。
其它还有Membership,Compression,RequestFilter,Analytics,Compression模块。Analytics这个功能我觉得对于很多监测网站数据访问量的人员来说是个很好的参考。
我会把对它的说明和Requestfilter放在一块讲解。估计接下来Http Module部分还得写7-8篇文章才行。
Cheers
Nic