对ASP.Net的认识(三)
较为详细的整个请求处理流程
Application: BeginRequest
Application: PreAuthenticateRequest
Application: AuthenticateRequest
Application: PostAuthenticateRequest
Application: PreAuthorizeRequest
Application: AuthorizeRequest
Application: PostAuthorizeRequest
Application: PreResolveRequestCache
Application: ResolveRequestCache
Application: PostResolveRequestCache
Application: PreMapRequestHandler
Page: Construct
Application: PostMapRequestHandler
Application: PreAcquireRequestState
Application: AcquireRequestState
Application: PostAcquireRequestState
Application: PreRequestHandlerExecute
Page: AddParsedSubObject
Page: CreateControlCollection
Page: AddedControl
Page: AddParsedSubObject
Page: AddedControl
Page: ResolveAdapter
Page: DeterminePostBackMode
Page: PreInit
Control: ResolveAdapter
Control: Init
Control: TrackViewState
Page: Init
Page: TrackViewState
Page: InitComplete
Page: LoadPageStateFromPersistenceMedium
Control: LoadViewState
Page: EnsureChildControls
Page: CreateChildControls
Page: PreLoad
Page: Load
Control: DataBind
Control: Load
Page: EnsureChildControls
Page: LoadComplete
Page: EnsureChildControls
Page: PreRender
Control: EnsureChildControls
Control: PreRender
Page: PreRenderComplete
Page: SaveViewState
Control: SaveViewState
Page: SaveViewState
Control: SaveViewState
Page: SavePageStateToPersistenceMedium
Page: SaveStateComplete
Page: CreateHtmlTextWriter
Page: RenderControl
Page: Render
Page: RenderChildren
Control: RenderControl
Page: VerifyRenderingInServerForm
Page: CreateHtmlTextWriter
Control: Unload
Control: Dispose
Page: Unload
Page: Dispose
Application: PostRequestHandlerExecute
Application: PreReleaseRequestState
Application: ReleaseRequestState
Application: PostReleaseRequestState
Application: PreUpdateRequestCache
Application: UpdateRequestCache
Application: PostUpdateRequestCache
Application: EndRequest
Application: PreSendRequestHeaders
Application: PreSendRequestContent
Master Page的加载顺序
1、Master page中的用户控件的page_init
2、aspx页面中的用户控件的page_init
3、Master page的page_init
4、aspx页面的page_init
5、aspx页面的page_load
6、Master page的page_load
7、Master page中的用户控件的page_load
8、aspx页面中的用户控件的page_load
其实Master Page可以看成是一个控件。
何时使用DataGrid/DataList/Repeater
实现了IEnumerable接口的类的对象可以成为这三种数据控件的数据源。
DataGrid最终会生成一个table,所以DataGridItem类继承自TableRow类。而Repeater最终生成的控件是用户自定义的,所以RepeaterItem类与TableRow类没有任何关系。DataGrid和DataList继承自WebControl类,而Repeater继承自Control类,WebControl类包含一些设置样式的属性,如BackColor,ForeColor,CssStyle,BorderStyle等,而Repeater样式的设置必须在它的Template里完成。
DataGrid有很多功能但欠缺灵活性,使用DataGrid很便捷,因为很多功能都已经封装好,只需要设置下相应的属性即可,但也正因为这个好处,使得DataGrid比较呆板,只能使用已经做好的功能,修改现有功能会比较麻烦,而且DataGrid最终生成的是一个table,如果想生成多个table或者div,DataGrid就无能为力了。DataGrid的性能是最差的因为DataGrid会把几乎所有内容都放入它的ViewState中,如果要使用DataGrid的Sort,Paging和Edit功能就不能禁掉ViewState,这会使ViewState大到足以严重影响性能的程度。
DataList比起DataGrid更加灵活,它可以使一行有多条记录,既可以使用table也可以使用span,不过有许多功能DataList并没有实现,需要开发人员自己实现,这样虽然会让开发人员花费更多时间但增强了灵活性,DataList的性能比起DataGrid要好。
Repeater是最灵活的,但对开发人员的要求也是最高的,它会花费最多的开发时间,但可以实现很多DataGrid和DataList无法实现的效果和功能,而且性能是最好的。
Page继承自TemplateControl并且实现了IHttpHandler接口,TemplateControl继承自Control,Page本身就是个HttpHandler。
Page处理Request的流程大致如下代码所述,也就是页面处理的流程。
private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint)
{
// 1. PreInit
this.PerformPreInit();
// 2. Init
this.InitRecursive(null);
this.OnInitComplete(EventArgs.Empty);
// 对于Postback,插入下面处理
if (this.IsPostBack)
{
// 加载ViewState和ControlState,进行场景恢复
this.LoadAllState();
// 第一次处理PostData
this.ProcessPostData(this._requestValueCollection, true);
}
// 3. PreLoad
this.OnPreLoad(EventArgs.Empty);
// 4. Load
this.LoadRecursive();
// 对于Postback,插入下面处理
if (this.IsPostBack)
{
// 第二次处理PostData
this.ProcessPostData(this._leftoverPostData, false);
// 如果PostData表面某个Control数据发生变化,那么RaisePostDataChanged事件
this.RaiseChangedEvents();
// RaisePostBackEvent
this.RaisePostBackEvent(this._requestValueCollection);
}
this.OnLoadComplete(EventArgs.Empty);
// 对于CallBack,RaiseCallBackEvent
if (this.IsPostBack && this.IsCallback)
{
this.PrepareCallback(callbackControlID);
}
else if (!this.IsCrossPagePostBack)
{
// 5. PreRender
this.PreRenderRecursiveInternal();
}
// 对于CallBack, Render出CallBack的结果
if (this.IsCallback)
{
this.RenderCallback();
}
else if (!this.IsCrossPagePostBack)
{
this.PerformPreRenderComplete();
// 6. SaveViewStae和ControlState
this.SaveAllState();
this.OnSaveStateComplete(EventArgs.Empty);
// 7. Render 整个Control
this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));
}
}
其中,PerformPreInit方法代码如下,可以发现PreInit时主要初始化Themes,加载MasterPage。
private void PerformPreInit()
{
this.OnPreInit(EventArgs.Empty);
this.InitializeThemes();
this.ApplyMasterPage();
this._preInitWorkComplete = true;
}
Page以及每个Control都有个ControlState属性,该属性用于记录Page处理到哪个阶段了,例如Init阶段结束时,这个属性会被赋值ControlState.Initialized,从而表明Init阶段的结束。这个属性会被用于很多地方,例如当添加一个动态控件时,父控件的AddedControl方法就会检查这个属性,如果已经过了Init阶段,则直接初始化添加的控件。ControlState和ViewState最大的区别是ControlState是无法被禁止的,并且ControlState里有个ArrayList,这个ArrayList保存了需要处理PostBackData的Control的ID,当处理PostBackData时就会从这个ArrayList里获取需要处理的Control的ID。
下面是Control.AddedControl方法的代码,
protected internal virtual void AddedControl(Control control, int index)
{
// 1. 初始化Page,Parent,NameContainer,ID
control._parent = this;
control._page = this.Page;
control.flags.Clear(0x20000);
Control namingContainer = this.flags[0x80] ? this : this._namingContainer;
if (namingContainer != null)
{
control.UpdateNamingContainer(namingContainer);
if ((control._id == null) && !control.flags[0x40])
{
control.GenerateAutomaticID();
}
else if ((control._id != null) || ((control._occasionalFields != null) && (control._occasionalFields.Controls != null)))
{
namingContainer.DirtyNameTable();
}
}
// 2. 判断当前Control所在的页面生命周期阶段,然后对于新加入的Control进行补充调用
if (this._controlState >= ControlState.ChildrenInitialized)
{
control.InitRecursive(namingContainer);
if (((control._controlState >= ControlState.Initialized) && (control.RareFields != null)) && control.RareFields.RequiredControlState)
{
this.Page.RegisterRequiresControlState(control);
}
if (this._controlState >= ControlState.ViewStateLoaded)
{
object savedState = null;
if ((this._occasionalFields != null) && (this._occasionalFields.ControlsViewState != null))
{
savedState = this._occasionalFields.ControlsViewState[index];
if (this.LoadViewStateByID)
{
control.EnsureID();
savedState = this._occasionalFields.ControlsViewState[control.ID];
this._occasionalFields.ControlsViewState.Remove(control.ID);
}
else
{
savedState = this._occasionalFields.ControlsViewState[index];
this._occasionalFields.ControlsViewState.Remove(index);
}
}
control.LoadViewStateRecursive(savedState);
if (this._controlState >= ControlState.Loaded)
{
control.LoadRecursive();
if (this._controlState >= ControlState.PreRendered)
{
control.PreRenderRecursiveInternal();
}
}
}
}
}
Control的卸载也是递归调用的。
对于需要用ASP.Net进行身份验证的页面,即使所有内容是静态的,也需要将后缀名改成aspx而不能用html,这是因为html将不会被ASP.Net的ISAPI所处理,也就无法进行身份验证。
aspx页面一般有ASP.Net自带的页处理程序来处理,它是Http处理程序中的一种,另外还有处理asmx的Web服务处理程序,如果需要针对特别的后缀名进行特别处理,需要创建一个自定义的Http处理程序,然后在IIS中将扩展名映射到ASP.Net的ISAPI中,并且在Web.config中注册这个处理程序。在Web.config中的注册如下代码所示
<configuration>
<system.web>
<httpHandlers> <add verb="*" path="*.sample" type="MyHandler"/></httpHandlers>
</system.web>
</configuration>
创建一个自定义的Http处理程序,有两种方式,
1、实现IHttpHandler接口创建同步处理程序
2、实现IHttpAsyncHandler接口创建异步处理程序
这个两个接口都需要实现IsReusable属性和ProcessRequest方法。IsReusable属性用于确定HttpHandlerFacotry对象(接收请求并调用相应的处理程序的对象)是否可以把该处理程序放入池中以便重复使用来提高性能,如果不可以的话,那么每次都要创建一个该处理程序的实例。ProcessRequest方法用于处理单个Http请求。如果Http处理程序的扩展名为ashx,那么这个处理程序会自动注册到IIS和ASP.Net中。异步处理程序可以启动一个外部进程,ASP.Net会将用于外部进程的线程放回线程池中以提高性能,直至外部进程处理结束进行回调为止。异步处理程序还必须实现BeginProcessRequest和EndProcessRequest方法。
另外可以通过实现IHttpHandlerFactory接口来自定义HttpHandlerFactory,这样做更具有灵活性,可以根据Http请求的具体命令(HttpContext.Request.RequestType,如PUT,GET,POST等)做一些处理,例如对于不同的命令调用不同的处理程序。在创建了自定义的HttpHandlerFactory以后需要在Web.config和IIS中进行注册。在Web.config中添加如下代码
<configuration>
<system.web>
<httpHandlers> <add verb="GET,POST" path="*.sample" type="MyHandlerFactory" /> </httpHandlers>
</system.web>
</configuration>
在IIS中需要对文件后缀名与ASP.Net的ISAPI进行映射。
ApplicationManager类在asp.net 2.0及之后版本用于创建并管理AppDomain。
对ASP.Net的认识(三)的更多相关文章
- ASP.NET MVC 视图(三)
ASP.NET MVC 视图(三) 前言 上篇对于Razor视图引擎和视图的类型做了大概的讲解,想必大家对视图的本身也有所了解,本篇将利用IoC框架对视图的实现进行依赖注入,在此过程过会让大家更了解的 ...
- ASP.NET MVC 路由(三)
ASP.NET MVC路由(三) 前言 通过前两篇的学习会对路由系统会有一个初步的了解,并且对路由系统中的Url规则有个简单的了解,在大家的脑海中也有个印象了,那么路由系统在ASP.NETMVC中所处 ...
- ASP.NET MVC 过滤器(三)
ASP.NET MVC 过滤器(三) 前言 本篇讲解行为过滤器的执行过程,过滤器实现.使用方式有AOP的意思,可以通过学习了解过滤器在框架中的执行过程从而获得一些AOP方面的知识(在顺序执行的过程中, ...
- Asp.Net中的三种分页方式
Asp.Net中的三种分页方式 通常分页有3种方法,分别是asp.net自带的数据显示空间如GridView等自带的分页,第三方分页控件如aspnetpager,存储过程分页等. 第一种:使用Grid ...
- 小白开学Asp.Net Core《三》
小白开学Asp.Net Core<三> ——界面 我胡汉三再次又回来了(距离上篇时间有点长),今天抽时间将最近对框架采用的后台界面做个记录 1.先上图 (图一) (图二) 2.界面说明 后 ...
- ASP.NET MVC 第三回 Controller与View
这节我们让ASP.NET MVC真正的跑起来 一.新建Controller 首先我们自己新建一个新的Controller在Controllers上点右键,添加,Controller选项 之后出现一 ...
- Pro ASP.NET MVC –第三章 MVC模式
在第七章,我们将创建一个更复杂的ASP.NET MVC示例,但在那之前,我们会深入ASP.NET MVC框架的细节:我们希望你能熟悉MVC设计模式,并且考虑为什么这样设计.在本章,我们将讨论下列内容 ...
- ASP.Net 中的三种控件
---恢复内容开始--- 第一种:HTML控件 ASP.Net把HTML控件当成普通字符串渲染到浏览器端,不去检查正确性.无法在服务器端进行处理. 比如: <input111 type=&quo ...
- Asp.Net中的三种分页方式总结
本人ASP.net初学,网上找了一些分页的资料,看到这篇文章,没看到作者在名字,我转了你的文章,只为我可以用的时候方便查看,2010的文章了,不知道这技术是否过期. 以下才是正文 通常分页有3种方法, ...
- ASP.NET MVC 4 (三) 过滤器
先来看看一个例子演示过滤器有什么用: public class AdminController : Controller { // ... instance variables and constru ...
随机推荐
- android安卓 SQLite教程:内部架构及SQLite使用办法
SQLite 介绍 SQLite一个非常流行的嵌入式数据库,它支持SQL语言,并且只利用很少的内存就有很好的性能.由于JDBC不适合手机这种内存受限设备,所以Android开发人员需要学习新的API ...
- HTML之一 符号实体
符号实体和”语言代码“以及”字符集“无关.
- 如何理解js
1.js/dom功能 2.performance 3.code organization 4.tools and flow 如何理解js代码,代码即业务. 如何快速理解代码业务.
- linux修改history
1.cat ~/.bash_history cat -n ~/.bash_history [以行数的形式查看] 2.history | more Enter 键盘 ----------一行一行 空 ...
- Mybatis-Generator 自动生成Dao、Model、Mapping相关文档
最近在学习mybatis,结果在写Mapping的映射文件时insert语句一直报错,于是想看看标准的映射文件是什么样.百度到Mybatis-Generator 自动生成Dao.Model.Mappi ...
- sqoop1.99.4安装与简介
1.什么是sqoop clouder公司开发的一个在关系数据库和hdfs,hive之间数据导入导出的一个工具 2.版本及其区别 现在分为sqoop1和sqoop2 1)架构图(sqoop1和hadoo ...
- 完整HttpHelper类
[代码] [C#]代码 using System; using System.Collections.Generic; using System.Text; using System.Net; usi ...
- WPF 之 布局(三)
六.DockPanel DockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列,这些对象位于 Children 属性中.停靠面板其实就是在WinForm类似于Dock属性的元 素 ...
- javaEE学习笔记-单例模式
定义: 确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 单例模式的三要素: (1)私有的静态的成员变量 (2)私有的构造方法 (3)公共的静态的入口点方法 单例模式的分类: (1)饿 ...
- 设置eclipse在linux下提示
在Windows下eclipse按alt+/就可以提示,但是在Linux下eclipse的设置不是这样的alt+/为切换输入法,如果要修改于Windows下的一样就需要修改一下快捷键: 点击windo ...