众所周知,每个asp.net页面都是一个HttpHandler,并且它也是一个控件。我们来看来它的本身定义。
public
class
Page : TemplateControl,IHttpHandler
{
}
当IIS处理http的请求时,都会根据请求的文件扩展名来判断,找到对应的ISAPI,ISAPI主要负责与
ASP.NET进程之间进行通信。Asp.net进程会进行一系统初始化工作,比如建立一个HttpRunTime运行
环境,等等一系统的操作,这个原理园子里很多朋友都写了,最终的请求都会找到一个Handler来执行,
我们平时写的asp.net页面就是一个handler,所以它可以处理请求,而这个Handler的入口点就是从
ProcessRequest()方法开始的。
上面说了这么废话,无非就是想说 ProcessRequest()这个方法到底干了些什么”勾当“,我从IL的
角度来重新认识它。
我先列出来Page类中一些非常重要的方法:
public
class
Page : TemplateControl,IHttpHandler
{
//
用于处理回发数据的方法
private
void
ProcessPostData(NameValueCollection postData,
bool
fBeforeLoad);
//
页面处理请求入口点
private
void
ProcessRequest();
//
调用了带参数的ProcessRequestMain()
private
void
ProcessRequestMain();
//
页面核心处理方法,执行一系列的我们平时熟悉的方法,事件(如Page_Init,Page_Load....)
private
void
ProcessRequestMain(
bool
includeStagesBeforeAsyncPoint,
bool
includeStagesAfterAsyncPoint);
}
我们先从入口处方法进入,先看看ProcessRequest();方法到底干了些什么,简单地注释了一下。
private
void
ProcessRequest()
{
//
设置语言文化信息
Thread currentThread
=
Thread.CurrentThread;
CultureInfo currentCulture
=
currentThread.CurrentCulture;
CultureInfo currentUICulture
=
currentThread.CurrentUICulture;
try
{
//
这其中又重载了一次
this
.ProcessRequest(
true
,
true
);
}
finally
{
this
.RestoreCultures(currentThread, currentCulture, currentUICulture);
}
}
//
我简化了代码
private
void
ProcessRequest(
bool
includeStagesBeforeAsyncPoint,
bool
includeStagesAfterAsyncPoint)
{
if
(includeStagesBeforeAsyncPoint)
{
this
.FrameworkInitialize();
//
框架初始化
}
try
{
//
这个才是重点,所有处理全在这个方法里
this
.ProcessRequestMain(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint);
}
catch
{
throw
;
}
}
终于讲到重点了。我们先看看ProcessRequestMain方法的IL,注释全写代码里了,基本都是我们平时熟悉的事件。
//
简化了许多,去掉了一些与调试与跟踪的代码
private
void
ProcessRequestMain(
bool
includeStagesBeforeAsyncPoint,
bool
includeStagesAfterAsyncPoint)
{
try
{
HttpContext context
=
this
.Context;
string
str
=
null
;
if
(includeStagesBeforeAsyncPoint)
{
//
预初始化,设置母版页与应用主题等操作
this
.PerformPreInit();
//
递归初始化,如果该控件包括子控件,则依次从内至外开始初始化(子控件->父控件)
this
.InitRecursive(
null
);
//
初始化完毕
this
.OnInitComplete(EventArgs.Empty);
//
如果为回发
if
(
this
.IsPostBack)
{
//
对那些启用了视图状态的控件依次加载视图数据,在这个阶段,我们非常熟悉的Page.LoadPageStateFromPersistenceMedium()
//
方法将会执行
this
.LoadAllState();
//
处理回发数据,该方法在load前与load之后都要执行,ProcessPostData这个方法说起来可以有一大堆,我准备另起一篇再讲这个
//
东东,在Page_Load之前执行时(即fBeforeLoad为true)时,它里面主要就是对那些实现了IPostBackDataHandler接口的控件
//
处理Post数据,注册Post数据处理事件,其实也就是很常见的LoadPostData();
//
RegisterRequiresRaiseEvent(control.PostBackEventHandler);保存那些未得到初始化的控件目的为了下一次的ProcessData..
//
.....等操作
this
.ProcessPostData(
this
._requestValueCollection,
true
);
}
//
终于快到页面加载了
this
.OnPreLoad(EventArgs.Empty);
//
循环执行Load事件,方法循环执行控件的Load事件,如果控件包括子控件,则从外到内执行(父控件->子控件),
//
执行顺序正常与InitRecursive()方法相反,Page_Load事件在此执行
this
.LoadRecursive();
if
(
this
.IsPostBack)
{
//
第二次处理回发数据,本次处理的控件上次没得到处理的剩下的控件
this
.ProcessPostData(
this
._leftoverPostData,
false
);
//
这个方法主要是引发那些需要处理回发数据的控件在数据改变时需要引发的事件,如textbox控件的textchanged事件
//
比如:postBackDataHandler.RaisePostDataChangedEvent();
this
.RaiseChangedEvents();
//
引起控件的回发事件,平时我们常用的控件的,如Button的click事件在这一步执行
this
.RaisePostBackEvent(
this
._requestValueCollection);
}
//
页面加载完毕
this
.OnLoadComplete(EventArgs.Empty);
}
//
验证
this
._request.ValidateRawUrl();
//
预呈现
this
.PerformPreRenderComplete();
//
保存视图状态 ,如: this.SavePageStateToPersistenceMedium(state);
this
.SaveAllState();
this
.OnSaveStateComplete(EventArgs.Empty);
//
最后一步当就就是呈现了。
this
.RenderControl(
this
.CreateHtmlTextWriter(
this
.Response.Output));
}
catch
(ThreadAbortException exception)
{
}
catch
(ConfigurationException)
{
}
catch
(Exception exception3)
{
}
}
这就是整个Page的从请求到输出整个一系统的执行过程,能过上面的代码能看得出来,Page页面大部分的处理逻辑都在 ProcessRequestMain()方法中,这就是我通过IL再一次看清楚Page的执行过程。希望能更清晰展示出来和大家 一起分享!
下一篇我会再分析一个页面是怎么处理ProcessPostData的。