最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

.NET页面page处理的过程讲解

来源:动视网 责编:小OO 时间:2025-09-30 08:17:59
文档

.NET页面page处理的过程讲解

一个Page处理的过程讲解背景知识Page类的派生关系Page是从TemplateControl中派生的,TemplateControl从Control派生。他们的定义分别如下://Control,从object派生,实现了四个接口publicclassControl:System.ComponentModel.IComponent,System.IDisposable,System.Web.UI.IParserAccessor,System.Web.UI.IDataBindingsAcces
推荐度:
导读一个Page处理的过程讲解背景知识Page类的派生关系Page是从TemplateControl中派生的,TemplateControl从Control派生。他们的定义分别如下://Control,从object派生,实现了四个接口publicclassControl:System.ComponentModel.IComponent,System.IDisposable,System.Web.UI.IParserAccessor,System.Web.UI.IDataBindingsAcces
一个Page处理的过程讲解

背景知识

Page类的派生关系

Page是从TemplateControl中派生的,TemplateControl从Control派生。他们的定义分别如下:

//Control,从object派生,实现了四个接口

public class Control : System.ComponentModel.IComponent, 

    System.IDisposable, 

    System.Web.UI.IParserAccessor, 

    System.Web.UI.IDataBindingsAccessor

{

}

//TemplateControl从Control派生,实现了接口System.Web.UI.INamingContainer

public abstract class TemplateControl : Control, System.Web.UI.INamingContainer

{

}

//Page从TemplateControl派生,实现了接口System.Web.UI. IHttpHandler

public class Page : TemplateControl, System.Web.IHttpHandler

{

}

而你编写的Page,你在_aspx.cs文件中编写的类是从Page派生,这个继承关系是你添加WebForm页面时,Visual Studio .net帮你建好的。而aspx的页面在运行时会被解释为一个从_aspx.cs文件中的类的派生类。(这里需要补充资料)。

    

正 题

猜想

当IIS接收到aspx页面一个请求,交给aspnet_isapi.dll处理。aspnet_isapi然后做以下的事情:

MyPage __p;

__p = new MyPage();

__p.ProcessRequest(System.Web.HttpContext.Current)

以上是我个人的估计,究竟事实是不是这样,我会找Microsoft的工程师要答案!我在System.Web.dll中没有找到处理产生Page实例的il,Page类的实例的创建可能是aspnet_isapi.dll作了,而aspnet_isapi.dll不是使用.net编写的,其内部的运行究竟如何无从得知。

以下不是猜想!

ProcessRequest(HttpContext)方法

Page中的ProcessRequest(System.Web.HttpContext)方法是这样的:

public virtual void ProcessRequest(Sunrise.Web.HttpContext context)

{

    this.SetIntrinsics(context); //进行最基本初始化

    this.ProcessRequest(); //处理请求

}

SetIntrinsics方法

从上面的代码可以看到,首先会调用SetIntrinsics(HttpContext context)方法,SetIntrinsics的作用是对Page的成员变量进行基本的初始化。SetIntrinsics如下:

//进行最基本初始化,设置_context、_request、_application、_cache的初值

private void  SetIntrinsics(HttpContext context)

{

    this._context = context;

    this._request =    context.Request;

    this._response = context.Response;

    this._application = context.Application;

    this._cache = context.Cache;

    if(this._clientTarget != null)

    {

        if(this._clientTarget.Length >0)

        {

            this._request.ClientTarget = this._clientTarget; 

        }

    }

    //调TempalateControl的HookUpAutomaticHandlers()方法初始化基本事件

    //包括:Init、Load、DataBinding、PreRender、Unload、Error、

    //AbortTransaction、CommitTransaction

    this.HookUpAutomaticHandlers(); 

}

ProcessRequest方法

然后就开始执行ProcessRequest()方法,大致如下:

try

{

    if(this.IsTransacted) //如果是事务状态

    {

        this.ProcessRequestTransacted();

    }

    else //非事务状态

    {

        this.ProcessRequestMain(); 

    }

    this.ProcessRequestEndTrace();

}

finally

{

    //释放资源,把_request、_response置为null,并执行UnloadRecursive(true)

    this.ProcessRequestCleanup();

}

ProcessRequestMain方法

通过上面的代码可以知道,当一个Page是非事务模式是,响应ProcessRequestMain()。事实上,是事务模式时,也是调用ProcessRequestMain()。以下是关于ProcessRequestMain()方法的伪码:

//step1 调用Control.InitRecursive()进行递归初始化 Control的OnInit()方法将会在此时被调用

this.InitRecursive(null); 

//如果是回传状态

if(this.IsPostBack)

{

    //step2 装载ViewState

    ///装载Page的ViewState,Control的LoadViewState()方法将会在这里被调用

    this.LoadPageViewState(); 

    //step3 处理回传的数据,如果Control实现了System.Web.UI.IPostBackDataHandler,

    //LoadPostData()方法在此时被调用

    this.ProcessPostData(this._requestValueCollection, true); 

}

//step4 调用Control.LoadRecursive()方法装载SubControls

//Control的Load()方法在此时被调用

this.LoadRecursive(); 

//如果是回传状态

if(this.IsPostBack)

{

    //step 5 再次处理未处理完的回传数据,

    //注意第二次调用时第二个参数是false,而第一次是true

    //第二次处理回传数据的作用可能是用来处理在OnLoad中创建的Control的数据,??

    this.ProcessPostData(this._leftoverPostData, false); 

    //step6 响应数据更改事件,

    //如果Control实现了System.Web.UI.IPostBackDataHandler接口,

    //Control的RaisePostDataChangedEvent()方法在此时被调用

    this.RaiseChangedEvents(); 

    //step7 响应回传事件 __dopostback()

    //如果Control实现了System.Web.UI.IPostBackEventHandler接口,Control的RaisePostBackEvent()方法在此时执行

    this.RaisePostBackEvent(this._requestValueCollection); 

    //step8 调用Control的PreRenderRecursiveInternal()方法,

    //Control的OnPreRender()方法在此时被调用

    this.PreRenderRecursiveInternal(); 

}

//step9 BuiltTree 构建ViewState,

//ViewState使用通过LosFormatter对ViewState进行编码,保存在Trace中

this.BuildProfileTree("ROOTthis.EnableViewState); 

//step10 保存Page的ViewState

//Control的SaveViewState()方法

this.SavePageViewState(); 

//step11 输出

//Control的Render()方法在此时被调用

this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));

ProcessRequestMain方法图示

Unload

Dispose

Render

SaveViewState

BuildProfileTree

RaisePostBackEvents

RaiseChangeEvents

Load PostData

Load

Load PostData

Load ViewState

Init

ProcessRequestTransacted方法

事实上,在事务状态下,也是调用ProcessRequestMain()的,我们来看一下ProcessRequestTransacted的代码:

bool V_0;

System.Web.Util.TransactedCallback V_1;

V_0 = false;

//创建事务回调的delegate

V_1 = new System.Web.Util.TransactedCallback(this.ProcessRequestMain); 

//在事务环境下调用ProcessRequestMain()

System.Web.Util.Transactions.InvokeTransacted(

    V_1,

    (System.EnterpriseServices.TransactionOption)(this._transactionMode), 

    ref V_0

    );

if(V_0)

{

    this.OnAbortTransaction(System.EventArgs.Empty); //终止事务

}

else

{

    this.OnCommitTransaction(System.EventArgs.Empty); //提交事务

}

InitRecursive方法

在ProcessRequestMain 方法中,首先执行Control的InitRecursive方法。在InitRecursive中,OnInit方法被执行。具体如下:

internal void InitRecursive(System.Web.UI.Control namingContainer) //ok

{

    string V_0;

    int V_1;

    int V_2;

    System.Web.UI.Control V_3;

    if(this._controls != null)

    {

//flag[128]表示是否实现了System.Web.UI.INamingContainer接口

        if(this.flags[128])

        {

            namingContainer = this;

        }

        //设置_controls为只读,并返回原来的_readOnlyErrorMsg,保存在V_0

        V_0 = this._controls.SetCollectionReadOnly("Parent_collections_readonly"); 

        V_1 = this._controls.Count;

        for(V_2 = 0;V_2 < V_1; V_2++)

        {

            V_3 = this._controls[V_2];

            V_3._namingContainer = namingContainer;

            if(namingContainer != null)

            {

                if((V_3._id == null)

                    &&

                    (!(V_3.flags[]))

                    )

                {

                    this.GenerateAutomaticID();

                }

            }

            V_3._page = this._page;

            V_3.InitRecursive(namingContainer);

        }

        //回复_controls原来的状态

        this._controls.SetCollectionReadOnly(V_0);

        this._controlState = Sunrise.Web.UI.ControlState.Initialized;

        //OnInit方法在此时被调用

        this.OnInit(System.EventArgs.Empty); 

        this.TrackViewState(); 

    }

}

LoadPageViewState方法

在ProcessRequestMain 方法中,执行InitRecursive方法进行初始化后,如果Page的IsPostBack属性值为True,则会接着执行LoadPageViewState方法。

LoadPageViewState应该结合来SavePageViewState来看,这样更容易理解。具体如下:

internal void LoadPageViewState()

{

    System.Web.UI.Triplet V_0;

    string V_1;

    //获得使用LosFormater反序列化(Deserialize)得到的对象

    V_0 = (System.Web.UI.Triplet)this.LoadPageStateFromPersistenceMedium();

    if(V_0 != null)

    {

        V_1 = (string)V_0.First;

        int.Parse(V_1,System.Globalization.NumberFormatInfo.InvariantInfo);

        this.GetTypeHashCode();

        //判断V_1和Page调用GetTypeHashCode()方法获得的值是否相等,

//并把比较结果保存在_fPageLayoutChanged 

        this._fPageLayoutChanged = (int.Parse(V_1,System.Globalization.NumberFormatInfo.InvariantInfo) != this.GetTypeHashCode());

        if(!(this._fPageLayoutChanged))

        {

            //调用Control.LoadViewStateRecursive()方法,

//递归装载ViewState,

//Control的LoadViewState()方法将会在这里被执行

            this.LoadViewStateRecursive(V_0.Second); 

            this._controlsRequiringPostBack = (System.Collections.ArrayList)V_0.Third;

        }

    }

}

LoadViewStateRecursive方法

通过观察LoadPageViewState的代码可以得知,LoadPageViewState中执行LoadViewStateRecursive来进行Control的LoadViewState过程。

LoadViewStateRecursive的过程大致是这样,把参数savedState转换为Triplet对象,使用Triplet对象的First做参数来执行LoadView方法,然后使用Triplet对象的Second和Third对Controls进行LoadViewStateRecursive。

这个方法应该参照SaveViewStateRecursive一起阅读,这样更方便理解。如下:

internal void LoadViewStateRecursive(object savedState)

{

    System.Web.UI.Triplet V_0;

    System.Collections.ArrayList V_1;

    System.Collections.ArrayList V_2;

    Sunrise.Web.UI.ControlCollection V_3;

    int V_4;

    int V_5;

    int V_6;

    int V_7;

    //如果参数为null或EnableViewState为False

    if((savedState == null)

        || (this.flags[4]) //flags[4]表示EnableViewState,true时,EnableViewState为false,false时EnableViewState为true

        )

    {

        return;

    }

    //转换为Triplet对象,Triplet有三个public的Fields:First、Second、Third,使用Triplet表示使代码更直观,而且更快

    V_0 = (System.Web.UI.Triplet)savedState;

    //如果control的Page不为null,而且this.Page.IsPostBack为True,执行LoadViewState方法

    if((this.Page != null)

        && (this.Page.IsPostBack)

        )

    {

        this.LoadViewState(V_0.First);

    }

    //对this.Controls中的Control进行LoadViewState

    if(V_0.Second != null)

    {

        V_1 = (System.Collections.ArrayList)V_0.Second; //kes

        V_2 = (System.Collections.ArrayList)V_0.Third; //values

        V_3 = this.Controls;

        V_4 = V_3.Count;

        V_5 = V_1.Count;

        for(V_6=0; V_6 < V_5; V_6 ++)

        {

            V_7 = (int)V_1[V_6];

            if(V_7 < V_4)

            {

                V_3[V_7].LoadViewStateRecursive(V_2[V_6]);

            }

            else

            {

                if(this._controlsViewState == null)

                {

                    this._controlsViewState = new System.Collections.Hashtable();

                }

                this._controlsViewState[V_7] = V_2[V_6];

            }

        }

    }

    //将_controlState设置为ViewStateLoaded

    this._controlState = Sunrise.Web.UI.ControlState.ViewStateLoaded;

}

LoadViewState方法

    LoadViewState方法的是Protected,当你构建自己的Control时,可以重载它。此时你应该在你写的LoadViewState方法里执行base. LoadViewState(something)。Control的LoadViewState代码如下:

protected virtual void  LoadViewState(object savedState)

{

    object V_0;

    if(savedState != null)

    {

        this.ViewState.LoadViewState(savedState);

        V_0 = this.ViewState["Visible"];

        if(V_0 != null)

        {

            // flags[16]表示Visible,false时,Visible为true,值为false时,Visible为true

            this.flags[16] = (!((bool)V_0));

            this.flags[32] = true; // flags[32]表示是否已经LoadView 

        }

    }

}

ProcessPostData方法

当ProcessRequestMain执行了LoadPageViewState方法后,接着就是ProcessPostData,这个方法是用来处理回传数据。这个方法被执行两遍,分别在LoadRecursive之前和之后个执行一遍。第一次执行时,参数fBeforeLoad值为True,第二次为False。

//处理回传的数据

//当fBeforeLoad为true时,是第一次调用,fBeforeLoad为false时,为第二次调用

private void ProcessPostData(System.Collections.Specialized.NameValueCollection postData, bool fBeforeLoad) //ok

{

    string V_0;

    Sunrise.Web.UI.Control V_1;

    System.Web.UI.IPostBackDataHandler V_2;

    bool V_3;

    System.Collections.ArrayList V_4;

    string V_5;

    System.Web.UI.IPostBackDataHandler V_6;

    bool V_7;

    System.Collections.IEnumerator V_8;

    System.IDisposable V_9;

    if(this._changedPostDataConsumers == null)

    {

        this._changedPostDataConsumers = new System.Collections.ArrayList();

    }

    if(postData != null)

    {

        V_8 = postData.GetEnumerator();

        try

        {

            while(V_8.MoveNext())

            {

                V_0 = (string)V_8.Current;

                if(V_0 != null)

                {

                    //判断回传数据是否在系统PostFields内,

                    //s_systemPostFields包括__EVENTTARGET、__EVENTARGUMENT、__VIEWSTATE

                    if(!s_systemPostFields.Contains(V_0))

                    {

                        V_1 = this.FindControl(V_0); //在Page中查找匹配的Control

                        if((V_1 == null) //如果找不到,将数据保存在_leftoverPostData中

                            && (fBeforeLoad)

                            )

                        {

                            if(this._leftoverPostData == null)

                            {

                                this._leftoverPostData = new System.Collections.Specialized.NameValueCollection();

                            }

                            this._leftoverPostData.Add(V_0,null);

                        }

                        else //如果找到了……

                        {

                        //如果找到的结果实现了System.Web.UI.IPostBackDataHandler接口,

                            //调用RegisterRequiresRaiseEvent方法

//赋值给_registeredControlThatRequireRaiseEvent

                            if(!(V_1 is System.Web.UI.IPostBackDataHandler))

                            {

                                if(V_1 is System.Web.UI.IPostBackEventHandler)

                                {

                                    this.RegisterRequiresRaiseEvent(

                                        (System.Web.UI.IPostBackEventHandler)V_1

                                        );

                                }

                            }

                            else//如果找到的结果没有实现System.Web.UI.IPostBackDataHandler接口

                            {

                                V_2 = (System.Web.UI.IPostBackDataHandler)V_1;

                                V_3 = V_2.LoadPostData(V_0,this._requestValueCollection); //V_2装载回传数据

                                if(V_3) //如果V_2装载回传数据时发现数据已经被修改,将登记V_2在_changedPostDataConsumers中

                                {

                                    this._changedPostDataConsumers.Add(V_2);

                                }

                                //在_controlsRequiringPostBack中移去V_0

                                //_controlsRequiringPostBack的值在LoadPageViewState()方法中被赋值

                                if(this._controlsRequiringPostBack != null)

                                {

                                    this._controlsRequiringPostBack.Remove(V_0);

                                }

                            }

                        }

                    }

                }

            }

        }

        finally

        {

            V_9 = V_8 as System.IDisposable;

            if(V_9 != null)

            {

                V_9.Dispose();

            }

        }

    }

    V_4 = null;

    //处理_controlsRequiringPostBack中剩下的数据项

    if(this._controlsRequiringPostBack != null)

    {

        V_8 = this._controlsRequiringPostBack.GetEnumerator();

        try

        {

            while(V_8.MoveNext())

            {

                V_5 = (string)V_8.Current;

                V_6 = (System.Web.UI.IPostBackDataHandler)this.FindControl(V_5);

                if(V_6 != null)

                {

//V_7装载回传数据

                    V_7 = V_6.LoadPostData(V_5,this._requestValueCollection); 

//如果V_6装载回传数据时发现数据已经被修改,

//将登记V_6在_changedPostDataConsumers中

                    if(V_7)                    {

                        this._changedPostDataConsumers.Add(V_6);

                    }

                }

                else

                {

                    if(fBeforeLoad) //如果是第一次调用,保留

                    {

                        if(V_4 == null)

                        {

                            V_4 = new System.Collections.ArrayList();

                        }

                        V_4.Add(V_5);

                    }

                }

            }

        }

        finally

        {

            V_9 = V_8 as System.IDisposable;

            if(V_9 != null)

            {

                V_9.Dispose();

            }

        }

    }

//如果是第一次调用,值为未处理的数据项,第二次调用值为null

    this._controlsRequiringPostBack = V_4; 

}

LoadRecursive方法

LoadRecursive方法的过程大致是这样,先执行Load方法,然后对Controls执行LoadRecursive。

代码如下:

internal void LoadRecursive() 

{

    string V_0;

    int V_1;

    int V_2;

    //在这里执行OnLoad方法

    this.OnLoad(System.EventArgs.Empty);

    if(this._controls != null)

    {

        //设置_controls为只读

        V_0 = this._controls.SetCollectionReadOnly("Parent_collections_readonly");

        V_1 = this._controls.Count;

        for(V_2 = 0;V_2 < V_1; V_2++)

        {

            this._controls[V_2].LoadRecursive();

        }

        //回复原来的状态

        this._controls.SetCollectionReadOnly(V_0);

    }

    this._controlState = Sunrise.Web.UI.ControlState.Loaded;

}

RaiseChangedEvents方法

如果Control实现了System.Web.UI.IPostBackDataHandler接口,Control的RaisePostDataChangedEvent将会在这里被调用。需要的响应的RaisePostDataChangedEvent的典型例子是TextBox。TextBox的Text数据在客户端可能被修改,如果修改了,需要获得通知,以响应TextChanged事件。

internal void RaiseChangedEvents() //ok

{

    int V_0;

    System.Web.UI.IPostBackDataHandler V_1;

    Sunrise.Web.UI.Control V_2;

    if(this._changedPostDataConsumers != null)

    {

        for(V_0=0; V_0 < this._changedPostDataConsumers.Count; V_0++)

        {

            V_1 = (System.Web.UI.IPostBackDataHandler)this._changedPostDataConsumers[V_0];

            V_2 = V_1 as Sunrise.Web.UI.Control;

            //如果V_2是Page的SubControls,调用RaisePostDataChangedEvent()

            if((V_2 != null)

                ||

                (V_2.IsDescendentOf(this))

                )

            {

                V_1.RaisePostDataChangedEvent();

            }

        }

    }

}

RaisePostBackEvent方法

当执行Client端JavaScript的__dopostback()函数时,将产生回传事件。(此处需要补充资料)。回传事件的原理是,Page产生的HTML代码中,会产生两个隐藏域(Hidden),__EVENTTARGET和__ EVENTARGUMENT,不同的Control产生执行__dopostback()的方法不一致。调用的时候大多数是这样:

__dopostback(control_uniqueid, ‘’);

当Form提交的时候,RaisePostBackEvent中根据control_uniqueid来找到需要响应事件的Server Control。__ EVENTARGUMENT是事件的参数,参数在开发简单的Server Control通常是不需要,在复杂的Server Control时才用。

例如System.Web.UI.WebControls.LinkButton。

private void RaisePostBackEvent(System.Collections.Specialized.NameValueCollection postData) 

{

    string V_0;

    Sunrise.Web.UI.Control V_1;

    string V_2;

    if(this._registeredControlThatRequireRaiseEvent != null)

    {

        this.RaisePostBackEvent(_registeredControlThatRequireRaiseEvent, null);

        return;

    }

    V_0 = postData["__EVENTTARGET"];

    if((V_0 != null)

        &&

     (V_0.Length >0)

        )

    {

        V_1 = this.FindControl(V_0);

        if((V_1 != null)

            && (V_1 is System.Web.UI.IPostBackEventHandler)

            )

        {

            V_2 = postData["__EVENTARGUMENT"];

            this.RaisePostBackEvent((System.Web.UI.IPostBackEventHandler)V_1, V_2);

        }

    }

    else

    {

        this.Validate();

    }

}

PreRenderRecursiveInternal方法

    Control的PrenRender方法会在这里被执行。代码如下:

internal void PreRenderRecursiveInternal()

{

    string V_0;

    int V_1;

    int V_2;

    // flags[16]表示Visible,false时,Visible为true,值为false时,Visible为true

    if(!(this.flags[16]))

    {

        this.EnsureChildControls();

        //OnPreRender在这里被执行

        this.OnPreRender(System.EventArgs.Empty);

        if(this._controls != null)

        {

            //设置只读

            V_0 = this._controls.SetCollectionReadOnly("Parent_collections_readonly");

            V_1 = this._controls.Count;

            for(V_2 = 0;V_2 < V_1; V_2++)

            {

                this._controls[V_2].PreRenderRecursiveInternal();

            }

            //回复原来的状态

            this._controls.SetCollectionReadOnly(V_0);

        }

    }

    this._controlState = Sunrise.Web.UI.ControlState.PreRendered;

}

BuildProfileTree 方法

构建ViewState的存放空间,放在Trace里。(此处需要更详细的说明)

protected void BuildProfileTree(string parentId, bool calcViewState)

{

    int V_0;

    int V_1;

    int V_2;

    calcViewState = calcViewState || (!(this.flags[4]));

    if(calcViewState)

    {

        //计算LosFormatter会产生编码结果的长度

        V_0 = Sunrise.Web.UI.LosFormatter.EstimateSize(this.SaveViewState());

    }

    else

    {

        V_0 = 0;

    }

    this.Page.Trace.AddNewControl(

        this.UniqueID,

        parentId,

        this.GetType().FullName,

        V_0

        );

    if(this._controls != null)

    {

        V_1 = this._controls.Count;

        for(V_2 =0; V_2 < V_1; V_2 ++)

        {

            this._controls[V_2].BuildProfileTree(this.UniqueID, calcViewState);

        }

    }

SavePageViewState 方法

保存Page的ViewState,LosFormatter的编码结果放置于_viewStateToPersist中。此方法应该结合LoadPageViewState一起来分析。

使用Triplet和Pair保存ViewState时常用的技巧。这里使用了Triplet。

(需要补充关于LosFormatter的说明)

SavePageViewState和SavePageStateToPersistenceMedium的代码如下:

internal void SavePageViewState() 

{

    System.Web.UI.Triplet V_0;

    int V_1;

    if(!(this._needToPersistViewState))

    {

        return;

    }

    V_0 = new System.Web.UI.Triplet();

    V_1 = this.GetTypeHashCode();

    //将数字转换为字符

    V_0.First = V_1.ToString(System.Globalization.NumberFormatInfo.InvariantInfo);

    //_registeredControlsThatRequirePostBack是一个ArrayList,

    //其内容项 RegisterRequiresPostBack(System.Web.UI.Control control)来添加

    V_0.Third = this._registeredControlsThatRequirePostBack;

    if(this.Context.TraceIsEnabled)

    {

        this.Trace.AddControlViewstateSize(

            this.UniqueID,

            Sunrise.Web.UI.LosFormatter.EstimateSize(V_0)

            );

    }

//执行SaveViewStateRecursive()方法,把返回结果保存赋给V_0.Second。

    V_0.Second = this.SaveViewStateRecursive();

    this.SavePageStateToPersistenceMedium(V_0);

}

protected virtual void SavePageStateToPersistenceMedium(object viewState)

{

    this._viewStateToPersist = viewState;

}

SaveViewStateRecursive方法

在SavePageViewState方法中执行SaveViewStateRecursive方法来获取ControlTree的SaveViewState的结果。

internal object SaveViewStateRecursive() 

{

    object V_0;

    System.Collections.ArrayList V_1;

    System.Collections.ArrayList V_2;

    int V_3;

    int V_4;

    Sunrise.Web.UI.Control V_5;

    object V_6;

    System.Web.UI.Triplet V_7;

    if(this.flags[4])

    {

        return(null);

    }

    //获得Control本身的SaveViewState()结果

    V_0 = this.SaveViewState(); 

    V_1 = null;

    V_2 = null;

    

    //获取SubControls的SaveViewStateRecursive()结果

    if(this._controls != null)

    {

        V_3 = this._controls.Count;

        

        for(V_4=0; V_4        {

            V_5 = this._controls[V_4];

            V_6 = V_5.SaveViewStateRecursive();

            if(V_6 != null)

            {

                if(V_1 == null)

                {

                    V_1 = new System.Collections.ArrayList();

                    V_2 = new System.Collections.ArrayList();

                    V_1.Add(V_4);

                    V_2.Add(V_6);

                }

            }

        }

    }

    V_7 = null;

    //如果Control本身的SaveViewState()结果不为null,

    //而且SuControls的SaveViewStateRecursive()结果不为null

    if((V_0 != null)

        || (V_1 != null)

        )

    {

        V_7 = new System.Web.UI.Triplet(V_0, V_1, V_2);

    }

    return(V_7);

}

RenderControl方法

ProcessRequestMain()执行了PreRenderRecursive后,接着就执行RenderControl方法。RenderControl是在Control中定义的方法。RenderControl是执行Control的Render方法,输出html文本。

public void  RenderControl(System.Web.UI.HtmlTextWriter writer) //ok

{

    System.Web.HttpContext V_0;

    int V_1;

    int V_2;

    // flags[16]表示Visible,false时,Visible为true,值为false时,Visible为true

    if(!(this.flags[16]))

    {

        //如果this._page不为null,……

        V_0 = (this._page == null) ? null: this._page._context;

        if(V_0 != null)

        {

            if(V_0.TraceIsEnabled)

            {

                V_1 =V_0.Response.GetBufferedLength();

                //Render方法在这里被执行

                this.Render(writer);

                V_2 = V_0.Response.GetBufferedLength();

                V_0.Trace.AddControlSize(this.UniqueID, V_2 - V_1);

            }

        }

        else

        {

            //Render方法在这里被执行

            this.Render(writer);

        }

    }

}

Render和RenderChildren

Render和RenderChildren都可以被重载。在System.Web.UI.WebControls命名空间里,大部分Control都是从System.Web.UI.WebControls.WebControl中派生的,WebControl重载Render方法,分拆成三个方法,RenderBeginTage、RenderContent和RenderEndTag。如果Cotnrol是从WebControl中派生,通常只需要重载RenderContent。

下面是Control中的代码:

protected virtual void Render(System.Web.UI.HtmlTextWriter writer)

{

    this.RenderChildren(writer);

}

protected virtual void RenderChildren(System.Web.UI.HtmlTextWriter writer) //ok

{

    int V_0;

    int V_1;

    if(this._renderMethod != null)

    {

        this._renderMethod(writer,this);

    }

    else

    {

        if(this._controls != null)

        {

            V_0 = this._controls.Count;

            for(V_1=0; V_1            {

                this._controls[V_1].RenderControl(writer);

            }

        }

    }

}

文档

.NET页面page处理的过程讲解

一个Page处理的过程讲解背景知识Page类的派生关系Page是从TemplateControl中派生的,TemplateControl从Control派生。他们的定义分别如下://Control,从object派生,实现了四个接口publicclassControl:System.ComponentModel.IComponent,System.IDisposable,System.Web.UI.IParserAccessor,System.Web.UI.IDataBindingsAcces
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top