解读System.Web.UI.Page中关键方法ProcessRequestMain()

     为了更好地优化博客园程序的性能,最近我在优化代码的同时,更深入地去研究asp.net的源代码。asp.net的源代码通过Reflector工具一鉴无遗, 虽然不是原版的代码,但已经足够了,其中的原理与思想已经清楚地摆在我们面前。这是.NET开发人员的幸运! 
    在我们开发asp.net应用程序时, System.Web.UI.Page是我们最熟悉并用的最多的一个类。但有多少人真正对这个类的源代码仔细研究过? 从相关搜索中可以看出并不是很多,比如,用Google搜索ProcessRequestMain方法中开始的“OnPageStartSessionObjects”,结果只有四个。
     今天我花了半天时间,研究了Page中处理请求的最关键的方法:ProcessRequestMain(),在这里我将自己的理解写出来与大家共享,欢迎大家批评并指正。一切尽在代码注释中:

注:为了方便阅读与理解,已去掉源代码中输出Trace信息的部分。

public   class  Page
{
    
private   void  ProcessRequestMain()
    
{
        
try
        
{
            
if  ( this .IsInAspCompatMode)
            
{
                AspCompatApplicationStep.OnPageStartSessionObjects();
            }

            
// 将当前Context的Session中的对象传递给asp的OnStartPage
            
// 通过<%@ ASPCOMPAT="true" %>进行设置
            
// 参考文章:  http://samples.gotdotnet.com/quickstart/aspplus/doc/cominterop.aspx

            
this ._requestValueCollection  =   this .DeterminePostBackMode();
            
// 检查PostBackMode, 如果启用了PostBack, 获取VIEWSTATE数据并赋值给_requestValueCollection

            
base .InitRecursive( null );
            
// 调用基类的InitRecursive方法通过递归对子控件进行初始化, 比如: 生成控件ID,设置控件的Page属性。
            
// OnInit()方法将会在此时被调用
            
            
if  ( this .IsPostBack)
            
{
                
this .LoadPageViewState();
                
// 从_requestValueCollection通过反序列化载入视图状态数据,如果页面的Layout发生了改变,子控件重新递归载入(LoadViewStateRecursive)视图状态
                
// 载入后,从视图状态数据从得到所有要处理PostBack的控件并注册到_controlsRequiringPostBack. 

                
this .ProcessPostData( this ._requestValueCollection,  true );
                
// 处理PostBack数据, 从PostBack数据中得到所有控件ID并检查每个控件,如果不能在当前页面中找到该控件(FindControl), 将其存入_leftoverPostData.
                
// 如果存在该控件,继续检查,若该控件没有实现IPostBackDataHandler, 但实现了 IPostBackEventHandler,注册该控件进行事件处理。
                
// 若该控件实现了System.Web.UI.IPostBackDataHandler,该控件的LoadPostData()方法在此时被调用,并将其加入到_changedPostDataConsumers,
                
// 并从._controlsRequiringPostBack(LoadPageViewState时对它进行了赋值)中移除该控件.
                
// 这样就从_controlsRequiringPostBack中移除了所有实现IPostBackDataHandler接口的控件.
                
// 接着继续对 _controlsRequiringPostBack中余下的控件进行处理,但奇怪的是又对这些余下的控件检查是否存在并实现了IPostBackDataHandler, 如果实现,
                
// 调用该控件的LoadPostData()(有点多此一举了, 可能是Relector生成的代码有误)并放入_changedPostDataConsumers,如果没实现,放入一个新ArrayList变量,
                    //检查结束后,将其赋值给
_controlsRequiringPostBack.那现在_controlsRequiringPostBack中剩下什么呢?没有实现IPostBackDataHandler, 
                    //但实现了 IPostBackEventHandler的控件以及
没有被Load的控件, 也就是在PostBack数据中存在但FindControl没有找到的控件。
                    //为什么会有找不到的控件呢?我们这里需要注意的是OnLoad()事件还没执行,
                
// 有些控件还没有被加载.下面的base.LoadRecursive()就是触发OnLoad()事件的。

            }


            
base .LoadRecursive();
            
// 触发页面的OnLoad()事件->递归触发子控件的OnLoad()事件->将页面的_controlState状态设置为ControlState.Loaded

            
if  ( this .IsPostBack)
            
{
                
this .ProcessPostData( this ._leftoverPostData,  false );
                
// 理解了ProcessPostData(this._requestValueCollection, true)之后, 这个就很好理解了,就是检查_controlsRequiringPostBack中的控件是否存在并实现了
                
// IPostBackDataHandler, 如果实现,调用该控件的LoadPostData()方法并将其加入到_changedPostDataConsumers.ProcessPostData(this._leftoverPostData, false)
                
// 这个方法就是为OnLoad()之后加载的控件服务的。
                     }
                
this .RaiseChangedEvents();
                
// 在_changedPostDataConsumers(在两个ProcessPostData方法中向它添加了数据)中没有实现IPostBackDataHandler接口的控件触发RaisePostDataChangedEvent.

                
this .RaisePostBackEvent( this ._requestValueCollection);
                
// 触发_registeredControlThatRequireRaiseEvent及PostBack数据中实现IPostBackEventHandler接口的控件的RaisePostBackEvent事件。
        
        
            
base .PreRenderRecursiveInternal();
            
// 首先调用EnsureChildControls,检查子控件是否创建, 如果没有, 调用进行创建CreateChildControls.
            
// 触发OnPreRende事件.
            
// 递归调用子控件的PreRenderRecursiveInternal方法
            
// 设置._controlState为 ControlState.PreRendered

            
this .SavePageViewState();
            
// 保存视图状态数据至._viewStateToPersist 

            
base .RenderControl( this .CreateHtmlTextWriter( this .Response.Output));
            
// 输出当前及所有子控件的内容

        }

        
catch  (ThreadAbortException)
        
{
            
base .UnloadRecursive( true );
            
return ;
        }

        
catch  (ConfigurationException)
        
{
            
throw ;
        }

        
catch  (Exception exception1)
        
{
            PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
            PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
            
if  ( ! this .HandleError(exception1))
            
{
                
throw ;
            }

            
return ;
        }

    }

}
转载自:http://www.cnblogs.com/dudu/archive/2005/10/21/259328.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
帮我找出一下代码的错误,“/程序”应用程序的服务器错误。 “gvProducts”上同时定义了 DataSource 和 DataSourceID。请移除一个定义。 说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码导致错误的出处的详细信息。 异常详细信息: System.InvalidOperationException: “gvProducts”上同时定义了 DataSource 和 DataSourceID。请移除一个定义。 源错误: 行 39: this.gvProducts.DataSource = ds; 行 40: this.gvProducts.DataKeyNames = new string[] { "id" }; 行 41: this.gvProducts.DataBind(); 行 42: da.Dispose(); 行 43: conn.Dispose(); 源文件: c:\Users\86136\Desktop\第2组-网上书店系统\网上书店系统\程序\Myorderlist.aspx.cs 行: 41 堆栈跟踪: [InvalidOperationException: “gvProducts”上同时定义了 DataSource 和 DataSourceID。请移除一个定义。] System.Web.UI.WebControls.DataBoundControl.ConnectToDataSourceView() +8658325 System.Web.UI.WebControls.DataBoundControl.GetData() +4 System.Web.UI.WebControls.DataBoundControl.PerformSelect() +60 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73 System.Web.UI.WebControls.GridView.DataBind() +4 Myorderlist.bind_ordertables() in c:\Users\86136\Desktop\第2组-网上书店系统\网上书店系统\程序\Myorderlist.aspx.cs:41 Myorderlist.BindShopBasket() in c:\Users\86136\Desktop\第2组-网上书店系统\网上书店系统\程序\Myorderlist.aspx.cs:71 Myorderlist.Page_Load(Object sender, EventArgs e) in c:\Users\86136\Desktop\第2组-网上书店系统\网上书店系统\程序\Myorderlist.aspx.cs:26 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35 System.Web.UI.Control.OnLoad(EventArgs e) +99 System.Web.UI.Control.LoadRecursive() +50 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
最新发布
06-09

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值