终于明白了。
事情是这样的。
在对Page 类(System.Web.UI)进行了一些反编译之后,我发现 ASP.NET 在包括状态加载和保存在内的请求处理中基本上做了什么。以下代码是 ASP.NET 对方法 ProcessRequestMain 所做的:
this.Trace.Write("aspx.page", "Begin PreInit");
this.PerformPreInit();
this.Trace.Write("aspx.page", "End PreInit");
this.Trace.Write("aspx.page", "Begin Init");
this.InitRecursive((Control) null);
this.Trace.Write("aspx.page", "End Init");
this.Trace.Write("aspx.page", "Begin InitComplete");
this.OnInitComplete(EventArgs.Empty);
this.Trace.Write("aspx.page", "End InitComplete");
if (this.IsPostBack)
{
this.Trace.Write("aspx.page", "Begin LoadState");
this.LoadAllState();
this.Trace.Write("aspx.page", "End LoadState");
this.Trace.Write("aspx.page", "Begin ProcessPostData");
this.ProcessPostData(this._requestValueCollection, true);
this.Trace.Write("aspx.page", "End ProcessPostData");
}
this.Trace.Write("aspx.page", "Begin PreLoad");
this.OnPreLoad(EventArgs.Empty);
this.Trace.Write("aspx.page", "End PreLoad");
this.Trace.Write("aspx.page", "Begin Load");
this.LoadRecursive();
this.Trace.Write("aspx.page", "End Load");
if (this.IsPostBack)
{
this.Trace.Write("aspx.page", "Begin ProcessPostData Second Try");
this.ProcessPostData(this._leftoverPostData, false);
this.Trace.Write("aspx.page", "End ProcessPostData Second Try");
this.Trace.Write("aspx.page", "Begin Raise ChangedEvents");
this.RaiseChangedEvents();
this.Trace.Write("aspx.page", "End Raise ChangedEvents");
this.Trace.Write("aspx.page", "Begin Raise PostBackEvent");
this.RaisePostBackEvent(this._requestValueCollection);
this.Trace.Write("aspx.page", "End Raise PostBackEvent");
}
this.Trace.Write("aspx.page", "Begin LoadComplete");
this.OnLoadComplete(EventArgs.Empty);
this.Trace.Write("aspx.page", "End LoadComplete");
if (this.IsPostBack && this.IsCallback)
this.PrepareCallback(callbackControlID);
else if (!this.IsCrossPagePostBack)
{
this.Trace.Write("aspx.page", "Begin PreRender");
this.PreRenderRecursiveInternal();
this.Trace.Write("aspx.page", "End PreRender");
}
...
if (this.IsCallback)
{
this.RenderCallback();
}
else
{
if (this.IsCrossPagePostBack)
return;
this.Trace.Write("aspx.page", "Begin PreRenderComplete");
this.PerformPreRenderComplete();
this.Trace.Write("aspx.page", "End PreRenderComplete");
this.BuildPageProfileTree(this.EnableViewState);
this.Trace.Write("aspx.page", "Begin SaveState");
this.SaveAllState();
this.Trace.Write("aspx.page", "End SaveState");
this.Trace.Write("aspx.page", "Begin SaveStateComplete");
this.OnSaveStateComplete(EventArgs.Empty);
this.Trace.Write("aspx.page", "End SaveStateComplete");
this.Trace.Write("aspx.page", "Begin Render");
if (exportedWebPartID != null)
this.ExportWebPart(exportedWebPartID);
else
this.RenderControl(this.CreateHtmlTextWriter(this.Response.Output));
this.Trace.Write("aspx.page", "End Render");
this.CheckRemainingAsyncTasks(false);
}
方法LoadAllState()负责加载页面状态,它执行每个PostBack请求。
方法SaveAllState()负责保存页面状态。 ASP.NET 执行它的代码如下:
if (this.IsCallback)
{
this.RenderCallback();
}
else
{
...
this.SaveAllState();
...
}
这就是我的ViewState 没有在CallBack 请求中保存的原因!
所以,最后,解决方案!使用反射手动调用SaveAllState()方法!
if (Page.IsCallback)
{
System.Reflection.MethodInfo saveAllStateMethod = typeof(System.Web.UI.Page).GetMethod("SaveAllState", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
saveAllStateMethod.Invoke(Page, null);
}