在前面文章里說明了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