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

简介:

from:http://www.csharp.net.cn/post/62.html

为了更好地优化博客园程序的性能,最近我在优化代码的同时,更深入地去研究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
        }
 
    }
 
}
 

 

欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处!




















本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/archive/2009/12/10/1620864.html ,如需转载请自行联系原作者


相关文章
|
1月前
|
SQL 存储 安全
Web 常见攻击方式及防御方法
【10月更文挑战第25天】Web 安全是一个复杂而重要的领域,攻击者不断寻找新的攻击方法,我们需要不断加强防御措施,提高安全意识,以保障 Web 应用的安全运行。通过采取多种防御手段的综合运用,我们可以有效地降低 Web 攻击的风险,保护用户的信息和财产安全。同时,随着技术的不断发展,我们也需要持续关注和研究新的安全威胁和防御方法,以应对不断变化的安全形势。
297 56
|
1月前
|
存储 安全 Go
Web安全基础:防范XSS与CSRF攻击的方法
【10月更文挑战第25天】Web安全是互联网应用开发中的重要环节。本文通过具体案例分析了跨站脚本攻击(XSS)和跨站请求伪造(CSRF)的原理及防范方法,包括服务器端数据过滤、使用Content Security Policy (CSP)、添加CSRF令牌等措施,帮助开发者构建更安全的Web应用。
104 3
|
6月前
|
存储 开发框架 JavaScript
深入探讨Flutter中动态UI构建的原理、方法以及数据驱动视图的实现技巧
【6月更文挑战第11天】Flutter是高效的跨平台移动开发框架,以其热重载、高性能渲染和丰富组件库著称。本文探讨了Flutter中动态UI构建原理与数据驱动视图的实现。动态UI基于Widget树模型,状态变化触发UI更新。状态管理是关键,Flutter提供StatefulWidget、Provider、Redux等方式。使用ListView等可滚动组件和StreamBuilder等流式组件实现数据驱动视图的自动更新。响应式布局确保UI在不同设备上的适应性。Flutter为开发者构建动态、用户友好的界面提供了强大支持。
116 2
WEB端在线CAD中实现测量圆、测量面积的方法
实现在线CAD中测量圆和测量面积的功能开发,用户点击目标圆对象将自动标记出这个圆的半径、面积值和周长值,同时可以自定义选择标注文字的位置,测量圆功能能够快速掌握目标圆对象的数据信息,方便统计工程量。
WEB端在线CAD中实现测量圆、测量面积的方法
|
2月前
|
前端开发 JavaScript
掌握微前端架构:构建现代Web应用的新方法
本文介绍了微前端架构的概念及其在现代Web应用开发中的优势与实施方法。微前端架构通过将应用拆分成独立模块,提升了开发效率和灵活性。其核心优势包括技术栈灵活性、独立部署、团队协作及易于维护。文章详细阐述了定义边界、选择框架、管理状态和通信等关键步骤,并讨论了状态同步、样式隔离及安全性等挑战。微前端架构有望成为未来Web开发的重要趋势。
|
2月前
|
存储 前端开发 API
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
136 0
|
3月前
|
前端开发 JavaScript 持续交付
Web应用开发的方法
Web应用开发的方法
37 1
|
4月前
|
JavaScript 前端开发 开发者
JS 继承之谜:究竟有哪些神秘方法?Web 前端开发者必知的关键技巧待你揭开谜底!
【8月更文挑战第23天】JavaScript (JS) 是 Web 前端开发的关键语言,其中继承是面向对象编程的重要概念。本文探讨了 JS 中几种继承机制:原型链继承、构造函数继承及组合继承。原型链继承利用原型对象实现属性和方法的共享;构造函数继承通过在子类构造器内调用父类构造器实现私有属性的复制;组合继承结合两者优点,既支持属性共享又避免了属性被意外覆盖的风险。理解这些模式有助于开发者更高效地组织代码结构,提升程序质量。
36 1
|
4月前
|
前端开发 图形学
Unity精华☀️UI和物体可见性的判断方法
Unity精华☀️UI和物体可见性的判断方法
|
4月前
|
Java 开发者 关系型数据库
JSF与AWS的神秘之旅:如何在云端部署JSF应用,让你的Web应用如虎添翼?
【8月更文挑战第31天】在云计算蓬勃发展的今天,AWS已成为企业级应用的首选平台。本文探讨了在AWS上部署JSF(JavaServer Faces)应用的方法,这是一种广泛使用的Java Web框架。通过了解并利用AWS的基础设施与服务,如EC2、RDS 和 S3,开发者能够高效地部署和管理JSF应用。文章还提供了具体的部署步骤示例,并讨论了使用AWS可能遇到的挑战及应对策略,帮助开发者更好地利用AWS的强大功能,提升Web应用开发效率。
75 0

热门文章

最新文章