1、花絮:
第一次拿到dottext时,开始让我比较觉得比较奇怪的是
一、以floerggyy注册后通过URL: http://x.x.x.x/floerggyy即可进入自己的blog里
(其实忘了以前常做下载页面download.aspx也不过是处理了HttpHandler的虚页面而已,可能是见在.Text兴奋的连这些基本常识都忘了^_^)
二、居然可以拿用户名做用户的唯一标识但在表里面没有找到做为用户名UserName唯一约束的东东(到现在还不清楚在数据库哪个地方设置的,有知道的请指点下)
后来通过重得注册同一用户名查看抛出的异常信息,确认确实在有UserName做为唯一约束的东东。
唉,看来我对数据库一无所知。
...后来决定专写一篇关于URL重写的文章,后来看到dottext的原作者也简单介绍了下urlRewrite,于是这个想法就放弃了。
后来又有一些朋友问dottext关于URL的问题,看来还是写吧
2、配置文件WebConfig.config简单浏览
自定义配置节内容:
1<configsections>
2<section name="BlogConfigurationSettings" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework"></section>
3<section name="HandlerConfiguration" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework"></section>
4<section name="SearchConfiguration" type="Dottext.Framework.Util.XmlSerializerSectionHandler, Dottext.Framework"></section>
5<section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"></section>
6<section name="codeHighlighter" type="ActiproSoftware.CodeHighlighter.CodeHighlighterConfigurationSectionHandler, ActiproSoftware.CodeHighlighter"></section>
7</configsections>
HttpHandler的配置内容:
1<httphandlers>
2<add path="*.asmx" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="false" verb="*"></add>
3<add path="Error.aspx" type="System.Web.UI.PageHandlerFactory" verb="*"></add>
4<add path="*" type="Dottext.Common.UrlManager.UrlReWriteHandlerFactory,Dottext.Common" verb="*"></add>
5</httphandlers>
HttpModule的配置内容:
1<httpmodules>
2<add name="UrlReWriteModule" type="Dottext.Common.UrlManager.UrlReWriteModule, Dottext.Common"></add>
3<add name="EventHttpModule" type="Dottext.Framework.ScheduledEvents.EventHttpModule, Dottext.Framework"></add>
4</httpmodules>
见到一个陌生的项目首先打开它的配置文件看看,这是我的习惯:)
先看看一些重点的配置内容:
看完Web.config中的上述内容熟悉asp.net运行机制的朋友就明白,DotText代码的运行顺序。在这里我再简单重复下
aspnet的内部运行机制(若有不熟悉的朋友请参阅<
1<asp.net famework深度历险="">>这本书,它对做asp.net开发的朋友很有帮助):
2remote client Request---->IIS---->aspnet_isapi.dll-->aspnet_wp.exe-->HttpRuntime--->
3HttpModule--->HttpHandler Factory--->HttpHandler--->HttpHandler.ProcessRequest()-->Response client Request
4好了,题归正转,client Request首先是被HttpModule截获。当我们请求.text的URL: http://www.cnblogs.com/floerggyy/时,首先是
5Dottext.Common.UrlManager命名空间下类UrlReWriteModule的相关方法被调用。
6(为什么会被类UrlReWriteModule截获远程请求呢?上面HttpModule配置节的内容不是标明了吗???^_^
7明知故问,那么为Dottext.Framework.ScheduledEvents命名空间下的类EventHttpModule会不会截获远程请求?什么时候截获呢?
8当然是按先来后顺序了,中国的优良传统都忘了!!!
9(其实这样说也是不太准确的,这两个HttpModule确是按顺序执行的但在HttpModule里的一些事件中它们是交叉运行的,好了类EventHttpModule
10不在我们的计论范围内在下面的代码就不分析了,有对这块不明白的最好去看下上面推荐的那本书^_^)
11
123 、URL重写,部分代码分析(这块涉及到众多自定义配置节、HttpModule、HttpHandler的综合应用所以要理顺还是有点麻烦的,要有一小点分析别人代码的耐心。个人认为)
13
14类UrlReWriteModule的方法
15
16
17private void context_BeginRequest(object sender, EventArgs e){
18//它是主要作用是根据请求匹配正则表达式来设置是否重写客户所请求的URL(它默认是重写URL),注意这句代码UrlHelper.SetEnableUrlReWriting(context,false);
19if(ConfigProvider.Instance().IsAggregateSite){
20HttpContext context = ((HttpApplication)sender).Context;
21
22string path = context.Request.Path.ToLower();
23int iExtraStuff = path.IndexOf(".aspx");
24if(iExtraStuff > -1 || path.IndexOf(".") == -1) {
25if(iExtraStuff > -1)
26{
27path = path.Remove(iExtraStuff+5,path.Length - (iExtraStuff+5));
28}
29
30path = regexApplication.Replace(path,string.Empty,1,0);
31
32if(path == "" || path == "/" || regexPath.IsMatch(path))
33{
34UrlHelper.SetEnableUrlReWriting(context,false);
35}
36
37}else if(context.Request.Path.ToLower().IndexOf("services") > 0 && context.Request.Path.ToLower().IndexOf(".asmx") > 0 )
38{
39if(AlllowService(context))
40{
41if(context.Request.RequestType!="POST")
42{
43string regexstr=@"/\w+/services/";
44string url=Regex.Replace(context.Request.RawUrl,regexstr,"/services/",RegexOptions.IgnoreCase);
45context.RewritePath(url);
46}
47//string fileName =context.Request; //System.IO.Path.GetFileName(context.Request.Path);
48//context.RewritePath("~/Services/" + fileName);
49}else{
50context.Response.Clear();
51context.Response.End();
52}
53}
54
55}
56
57
58HttpModule处理完后(这句话并不正确,在这里是这样的)进入HttpHandler Factory,根据HttpHandler的配置内容我们可以马上找到这个类
59UrlReWriteHandlerFactory它是处理重写URL请求核心,在这里我详细分析下。
60它实现了IHttpHandlerFactory
61(看注释就知道这个类是很重要的了)
62
63
64HttpModule处理完后(这句话并不正确,在这里是这样的)进入HttpHandler Factory,根据HttpHandler的配置内容我们可以马上找到这个类
65UrlReWriteHandlerFactory它是处理重写URL请求核心,在这里我详细分析下。
66它实现了IHttpHandlerFactory
67(看注释就知道这个类是很重要的了)
68
69using System;
70using System.Web;
71using System.Web.UI;
72using System.Text.RegularExpressions;
73
74using Dottext.Framework;
75using Dottext.Framework.Components;
76using Dottext.Framework.Configuration;
77
78namespace Dottext.Common.UrlManager
79{
80/**//// <summary>
81/// Class responisble for figuring out which .Text page to load. By default will load an array of Dottext.UrlManager.HttpHanlder
82/// from the blog.config file. This contains a list of Regex patterns to match the current request to. It also allows caching of the
83/// Regex's and Types
84/// </summary>
85public class UrlReWriteHandlerFactory: IHttpHandlerFactory
86{
87public UrlReWriteHandlerFactory(){} //Nothing to do in the cnstr
88//自定义虚方法从自定义配置节内容反序列化时构造Httphandler
89protected virtual HttpHandler[] GetHttpHandlers(HttpContext context)
90{
91return HandlerConfiguration.Instance().HttpHandlers;
92}
93
94/**//// <summary>
95/// Implementation of IHttpHandlerFactory. By default, it will load an array of HttpHanlder (Dottext.UrlManager.HttpHandler) from
96/// the blog.config. This can be changed, by overrideing the GetHttpHandlers(HttpContext context) method.
97/// </summary>
98/// <param name="context"/>Current HttpContext
99/// <param name="requestType"/>Request Type (Passed along to other IHttpHandlerFactory's)
100/// <param name="url"/>The current requested url. (Passed along to other IHttpHandlerFactory's)
101/// <param name="path"/>The physical path of the current request. Is not gaurenteed to exist (Passed along to other IHttpHandlerFactory's)
102/// <returns>
103/// Returns an Instance of IHttpHandler either by loading an instance of IHttpHandler or by returning an other
104/// IHttpHandlerFactory.GetHanlder(HttpContext context, string requestType, string url, string path) method
105/// </returns>
106//实现接口IHttpHandlerFactory定义的方法
107public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string path)
108{
109//Get the Handlers to process. By defualt, we grab them from the blog.config
110HttpHandler[] items = GetHttpHandlers(context);
111//Dottext.Framework.Logger.LogManager.Log("path",Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath));
112//Do we have any?
113if(items != null)
114{
115int count = items.Length;
116
117for(int i = 0; i<count; i++)
118{
119//We should use our own cached Regex. This should limit the number of Regex's created
120//and allows us to take advantage of RegexOptons.Compiled
121//逐个匹配所配置节中定义的请求类型
122if(items[i].IsMatch(Dottext.Framework.Util.Globals.RemoveAppFromPath(context.Request.Path,context.Request.ApplicationPath)))
123{
124//注意这里是关键,注意返回的Httphandler实例
125//throw new Exception();
126switch(items[i].HandlerType)
127{
128case HandlerType.Page://默认是Page
129
130return ProccessHandlerTypePage(items[i],context,requestType,url);
131case HandlerType.Direct:
132HandlerConfiguration.SetControls(context,items[i].BlogControls);
133return (IHttpHandler)items[i].Instance();
134case HandlerType.Factory:
135//Pass a long the request to a custom IHttpHandlerFactory
136return ((IHttpHandlerFactory)items[i].Instance()).GetHandler(context,requestType,url,path);
137default:
138throw new Exception("Invalid HandlerType: Unknown");
139}
140}
141}
142}
143//If we do not find the page, just let ASP.NET take over
144return PageHandlerFactory.GetHandler(context,requestType,url, path);
145}
146
147
148private IHttpHandler ProccessHandlerTypePage(HttpHandler item, HttpContext context, string requestType, string url)
149{
150string pagepath = item.FullPageLocation;
151if(pagepath == null)
152{
153pagepath = HandlerConfiguration.Instance().FullPageLocation;
154}
155HandlerConfiguration.SetControls(context,item.BlogControls);
156IHttpHandler myhandler=PageParser.GetCompiledPageInstance(url,pagepath,context);
157return myhandler;
158}
159
160
161public virtual void ReleaseHandler(IHttpHandler handler)
162{
163
164}
165}
166}
167
168要注意它是如何把自定义配置节中的内容拈合成httphandler的实例
169把这些理顺后对于理解.text的url重写就不难了....
170
171对上面若有理解不正解的欢迎高手指正</asp.net>