1、花絮:
第一次拿到dottext時(shí),開始讓我比較覺得比較奇怪的是
一、以floerggyy注冊后通過url:http://x.x.x.x/floerggyy即可進(jìn)入自己的blog里
(其實(shí)忘了以前常做下載頁面download.aspx也不過是處理了httphandler的虛頁面而已,可能是見在.text興奮的連這些基本常識(shí)都忘了^_^)
二、居然可以拿用戶名做用戶的唯一標(biāo)識(shí)但在表里面沒有找到做為用戶名username唯一約束的東東(到現(xiàn)在還不清楚在數(shù)據(jù)庫哪個(gè)地方設(shè)置的,有知道的請(qǐng)指點(diǎn)下)
后來通過重得注冊同一用戶名查看拋出的異常信息,確認(rèn)確實(shí)在有username做為唯一約束的東東。
唉,看來我對(duì)數(shù)據(jù)庫一無所知。
...后來決定專寫一篇關(guān)于url重寫的文章,后來看到dottext的原作者也簡單介紹了下urlrewrite,于是這個(gè)想法就放棄了。
后來又有一些朋友問dottext關(guān)于url的問題,看來還是寫吧
2、配置文件webconfig.config簡單瀏覽
自定義配置節(jié)內(nèi)容:
<configsections>
<section name="blogconfigurationsettings" type="dottext.framework.util.xmlserializersectionhandler, dottext.framework" />
<section name="handlerconfiguration" type="dottext.framework.util.xmlserializersectionhandler, dottext.framework" />
<section name="searchconfiguration" type="dottext.framework.util.xmlserializersectionhandler, dottext.framework" />
<section name="microsoft.web.services" type="microsoft.web.services.configuration.webservicesconfiguration, microsoft.web.services, version=2.0.0.0, culture=neutral, publickeytoken=31bf3856ad364e35" />
<section name="codehighlighter" type="actiprosoftware.codehighlighter.codehighlighterconfigurationsectionhandler, actiprosoftware.codehighlighter" />
</configsections>
httphandler的配置內(nèi)容:
<httphandlers>
<add verb="*" path="*.asmx" type="system.web.services.protocols.webservicehandlerfactory, system.web.services, version=1.0.5000.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a"
validate="false" />
<add verb="*" path="error.aspx" type="system.web.ui.pagehandlerfactory" />
<add verb="*" path="*" type="dottext.common.urlmanager.urlrewritehandlerfactory,dottext.common" />
</httphandlers>
httpmodule的配置內(nèi)容:
<httpmodules>
<add name="urlrewritemodule" type="dottext.common.urlmanager.urlrewritemodule, dottext.common" />
<add name="eventhttpmodule" type="dottext.framework.scheduledevents.eventhttpmodule, dottext.framework" />
</httpmodules>
見到一個(gè)陌生的項(xiàng)目首先打開它的配置文件看看,這是我的習(xí)慣:)
先看看一些重點(diǎn)的配置內(nèi)容:
看完web.config中的上述內(nèi)容熟悉asp.net運(yùn)行機(jī)制的朋友就明白,dottext代碼的運(yùn)行順序。在這里我再簡單重復(fù)下
aspnet的內(nèi)部運(yùn)行機(jī)制(若有不熟悉的朋友請(qǐng)參閱<<asp.net famework深度歷險(xiǎn)>>這本書,它對(duì)做asp.net開發(fā)的朋友很有幫助):
remote client request---->iis---->aspnet_isapi.dll-->aspnet_wp.exe-->httpruntime--->
httpmodule--->httphandler factory--->httphandler--->httphandler.processrequest()-->response client request
好了,題歸正轉(zhuǎn),client request首先是被httpmodule截獲。當(dāng)我們請(qǐng)求.text的url:http://www.cnblogs.com/floerggyy/時(shí),首先是
dottext.common.urlmanager命名空間下類urlrewritemodule的相關(guān)方法被調(diào)用。
(為什么會(huì)被類urlrewritemodule截獲遠(yuǎn)程請(qǐng)求呢?上面httpmodule配置節(jié)的內(nèi)容不是標(biāo)明了嗎???^_^
明知故問,那么為dottext.framework.scheduledevents命名空間下的類eventhttpmodule會(huì)不會(huì)截獲遠(yuǎn)程請(qǐng)求?什么時(shí)候截獲呢?
當(dāng)然是按先來后順序了,中國的優(yōu)良傳統(tǒng)都忘了!!!
(其實(shí)這樣說也是不太準(zhǔn)確的,這兩個(gè)httpmodule確是按順序執(zhí)行的但在httpmodule里的一些事件中它們是交叉運(yùn)行的,好了類eventhttpmodule
不在我們的計(jì)論范圍內(nèi)在下面的代碼就不分析了,有對(duì)這塊不明白的最好去看下上面推薦的那本書^_^)
3 、url重寫,部分代碼分析(這塊涉及到眾多自定義配置節(jié)、httpmodule、httphandler的綜合應(yīng)用所以要理順還是有點(diǎn)麻煩的,要有一小點(diǎn)分析別人代碼的耐心。個(gè)人認(rèn)為)
類urlrewritemodule的方法
private void context_beginrequest(object sender, eventargs e){
//它是主要作用是根據(jù)請(qǐng)求匹配正則表達(dá)式來設(shè)置是否重寫客戶所請(qǐng)求的url(它默認(rèn)是重寫url),注意這句代碼urlhelper.setenableurlrewriting(context,false);
if(configprovider.instance().isaggregatesite){
httpcontext context = ((httpapplication)sender).context;
string path = context.request.path.tolower();
int iextrastuff = path.indexof(".aspx");
if(iextrastuff > -1 || path.indexof(".") == -1) {
if(iextrastuff > -1)
{
path = path.remove(iextrastuff+5,path.length - (iextrastuff+5));
}
path = regexapplication.replace(path,string.empty,1,0);
if(path == "" || path == "/" || regexpath.ismatch(path))
{
urlhelper.setenableurlrewriting(context,false);
}
}else if(context.request.path.tolower().indexof("services") > 0 && context.request.path.tolower().indexof(".asmx") > 0 )
{
if(alllowservice(context))
{
if(context.request.requesttype!="post")
{
string [email protected]"http://w+/services/";
string url=regex.replace(context.request.rawurl,regexstr,"/services/",regexoptions.ignorecase);
context.rewritepath(url);
}
//string filename =context.request; //system.io.path.getfilename(context.request.path);
//context.rewritepath("~/services/" + filename);
}else{
context.response.clear();
context.response.end();
}
}
}
httpmodule處理完后(這句話并不正確,在這里是這樣的)進(jìn)入httphandler factory,根據(jù)httphandler的配置內(nèi)容我們可以馬上找到這個(gè)類
urlrewritehandlerfactory它是處理重寫url請(qǐng)求核心,在這里我詳細(xì)分析下。
它實(shí)現(xiàn)了ihttphandlerfactory
(看注釋就知道這個(gè)類是很重要的了)
httpmodule處理完后(這句話并不正確,在這里是這樣的)進(jìn)入httphandler factory,根據(jù)httphandler的配置內(nèi)容我們可以馬上找到這個(gè)類
urlrewritehandlerfactory它是處理重寫url請(qǐng)求核心,在這里我詳細(xì)分析下。
它實(shí)現(xiàn)了ihttphandlerfactory
(看注釋就知道這個(gè)類是很重要的了)
using system;
using system.web;
using system.web.ui;
using system.text.regularexpressions;
using dottext.framework;
using dottext.framework.components;
using dottext.framework.configuration;
namespace dottext.common.urlmanager
{
/**//// <summary>
/// class responisble for figuring out which .text page to load. by default will load an array of dottext.urlmanager.httphanlder
/// from the blog.config file. this contains a list of regex patterns to match the current request to. it also allows caching of the
/// regex’s and types
/// </summary>
public class urlrewritehandlerfactory: ihttphandlerfactory
{
public urlrewritehandlerfactory(){} //nothing to do in the cnstr
//自定義虛方法從自定義配置節(jié)內(nèi)容反序列化時(shí)構(gòu)造httphandler
protected virtual httphandler[] gethttphandlers(httpcontext context)
{
return handlerconfiguration.instance().httphandlers;
}
/**//// <summary>
/// implementation of ihttphandlerfactory. by default, it will load an array of httphanlder (dottext.urlmanager.httphandler) from
/// the blog.config. this can be changed, by overrideing the gethttphandlers(httpcontext context) method.
/// </summary>
/// <param name="context">current httpcontext</param>
/// <param name="requesttype">request type (passed along to other ihttphandlerfactory’s)</param>
/// <param name="url">the current requested url. (passed along to other ihttphandlerfactory’s)</param>
/// <param name="path">the physical path of the current request. is not gaurenteed to exist (passed along to other ihttphandlerfactory’s)</param>
/// <returns>
/// returns an instance of ihttphandler either by loading an instance of ihttphandler or by returning an other
/// ihttphandlerfactory.gethanlder(httpcontext context, string requesttype, string url, string path) method
/// </returns>
//實(shí)現(xiàn)接口ihttphandlerfactory定義的方法
public virtual ihttphandler gethandler(httpcontext context, string requesttype, string url, string path)
{
//get the handlers to process. by defualt, we grab them from the blog.config
httphandler[] items = gethttphandlers(context);
//dottext.framework.logger.logmanager.log("path",dottext.framework.util.globals.removeappfrompath(context.request.path,context.request.applicationpath));
//do we have any?
if(items != null)
{
int count = items.length;
for(int i = 0; i<count; i++)
{
//we should use our own cached regex. this should limit the number of regex’s created
//and allows us to take advantage of regexoptons.compiled
//逐個(gè)匹配所配置節(jié)中定義的請(qǐng)求類型
if(items[i].ismatch(dottext.framework.util.globals.removeappfrompath(context.request.path,context.request.applicationpath)))
{
//注意這里是關(guān)鍵,注意返回的httphandler實(shí)例
//throw new exception();
switch(items[i].handlertype)
{
case handlertype.page://默認(rèn)是page
return proccesshandlertypepage(items[i],context,requesttype,url);
case handlertype.direct:
handlerconfiguration.setcontrols(context,items[i].blogcontrols);
return (ihttphandler)items[i].instance();
case handlertype.factory:
//pass a long the request to a custom ihttphandlerfactory
return ((ihttphandlerfactory)items[i].instance()).gethandler(context,requesttype,url,path);
default:
throw new exception("invalid handlertype: unknown");
}
}
}
}
//if we do not find the page, just let asp.net take over
return pagehandlerfactory.gethandler(context,requesttype,url, path);
}
private ihttphandler proccesshandlertypepage(httphandler item, httpcontext context, string requesttype, string url)
{
string pagepath = item.fullpagelocation;
if(pagepath == null)
{
pagepath = handlerconfiguration.instance().fullpagelocation;
}
handlerconfiguration.setcontrols(context,item.blogcontrols);
ihttphandler myhandler=pageparser.getcompiledpageinstance(url,pagepath,context);
return myhandler;
}
public virtual void releasehandler(ihttphandler handler)
{
}
}
}
要注意它是如何把自定義配置節(jié)中的內(nèi)容拈合成httphandler的實(shí)例
把這些理順后對(duì)于理解.text的url重寫就不難了....
對(duì)上面若有理解不正解的歡迎高手指正