3.2 服务器端的处理
AJAX回发请求到达服务器之后,当前页面的生命周期跟普通回发引起的请求是一样的,页面的Init、Load和Render等等事件都会被触发,差别只是在于AJAX回发使用了不同的呈现画法。
AJAX回发引起的请求生命周期:
从上图我们可以看到,页面的生命周期与普通回发是一样的,同样页面上的控件也会经历相应的生命周期。
先了解一下ScriptManager控件在服务器端的处理:
- OnInit:在Init事件中,ScriptManager控件会注册页面的InitComplete, PreRenderComplete以及PreRender事件,另外还会根据本次请求的HTTP头来设定一个标记以确定本次回发是否为Ajax异步更新所引起的回发。
见下面的代码:
protected internal override void OnInit(EventArgs e) { base.OnInit(e); if (this.EnableHistory) { this.RegisterAsyncPostBackControl(this); } if (!base.DesignMode) { IPage iPage = this.IPage; if (GetCurrent(this.Page) != null) { throw new InvalidOperationException(AtlasWeb.ScriptManager_OnlyOneScriptManager); } iPage.Items[typeof(IScriptManager)] = this; iPage.Items[typeof(ScriptManager)] = this; iPage.InitComplete += new EventHandler(this.OnPageInitComplete); iPage.PreRenderComplete += new EventHandler(this.OnPagePreRenderComplete); if (iPage.IsPostBack) { this._isInAsyncPostBack = PageRequestManager.IsAsyncPostBackRequest(iPage.Request.Headers); if (this.EnableHistory) { this._isNavigating = iPage.Request["__EVENTTARGET"] == this.UniqueID; } } this.PageRequestManager.OnInit(); iPage.PreRender += new EventHandler(this.ScriptControlManager.OnPagePreRender); } }- OnPagePreRenderComplete,在PagePreRenderComplete事件中,ScriptManager控件会注册脚本文件以及Services代理脚本,MicrosoftAjax.js和MicrosoftAjaxWebForm.js就是在这个阶段被注册到客户端的。
见下面的代码:
private void OnPagePreRenderComplete(object sender, EventArgs e) { if (!this.IsInAsyncPostBack) { if (this.SupportsPartialRendering) { this.IPage.ClientScript.GetPostBackEventReference(new PostBackOptions(this, null, null, false, false, false, false, true, null)); } this.RegisterGlobalizationScriptBlock(); this.RegisterScripts(); this.RegisterServices(); if (this.EnableHistory) { JavaScriptSerializer serializer = JavaScriptSerializer.CreateInstance(); string[] strArray = new string[] { "\r\nSys.Application.setServerId(", serializer.Serialize(this.ClientID), ", ", serializer.Serialize(this.UniqueID), ");\r\n", ((this._initialState != null) && (this._initialState.Count != 0)) ? (" Sys.Application.setServerState('" + this.GetStateString() + "');\r\n") : "\r\n" }; string script = string.Concat(strArray); RegisterStartupScript(this, typeof(ScriptManager), "HistoryStartup", script, true); } } else { this.RegisterScripts(); if (this.EnableHistory) { if ((this._initialState != null) && (this._initialState.Count == 0)) { this._initialState = null; } if (this._newPointCreated) { this.RegisterDataItem(this, "'" + this.GetStateString() + "'", true); } } } }
- OnPreRender,在PreRender事件中如果判定本次回发为AJAX回发,则会调用PageRequestManager对象的OnPreRender方法。而PageRequestManager对象则会调用Page对象的SetRenderMethodDelegate方法来代理Page的画法,PageRequestManager对象会真正负责本次AJAX回发最终的HTML代码。
见下面的代码:
public class ScriptManager : Control, { protected internal override void OnPreRender(EventArgs e) { base.OnPreRender(e); if (this.IsInAsyncPostBack) { this.PageRequestManager.OnPreRender(); } } } internal sealed class PageRequestManager { internal void OnPreRender() { this._owner.IPage.SetRenderMethodDelegate(new RenderMethod(this.RenderPageCallback)); } }