C# 在回调请求时保持ViewState
问题是,我需要在C# 在回调请求时保持ViewState,c#,asp.net,session,callback,viewstate,C#,Asp.net,Session,Callback,Viewstate,问题是,我需要在回调请求期间保持ViewState 我知道,当请求是回调时,ASP.NET默认情况下不会保存页面状态。 所以,我需要一个替代方案来实现它 ASP.NET应用程序有一个自定义的PageStatePersister,它将所有页面状态(ViewState)存储到会话中。这样,ViewState在任何时候都不会发送/检索到客户端(尽管页面上仍然存在隐藏字段,但没有值)。ViewState不必在CallBack响应中返回,我只需要在正常的PostBack请求中调用保存ViewState的机
回调
请求期间保持ViewState
我知道,当请求是回调时,ASP.NET默认情况下不会保存页面状态。
所以,我需要一个替代方案来实现它
ASP.NET应用程序有一个自定义的PageStatePersister
,它将所有页面状态(ViewState
)存储到会话中。这样,ViewState
在任何时候都不会发送/检索到客户端(尽管页面上仍然存在隐藏字段,但没有值)。ViewState
不必在CallBack
响应中返回,我只需要在正常的PostBack
请求中调用保存ViewState
的机制
可能是这样的:
protected void Page_LoadComplete(object sender, EventArgs e)
{
//Set anything to the viewstate for accessing on a later postback
ViewState["Anything"] = 1;
if (Page.IsCallback)
{
//Persist the page state manualy (not needed on normal postback)
InvokeAspNetStateSaver();
}
...
}
protected override object SaveViewState()
{
object state = base.SaveViewState();
// your custom save logic
}
protected override void LoadViewState(object savedState)
{
object state = // load your view state here
base.LoadViewState(savedState);
}
感谢您的帮助。可以在第页的SaveState和LoadState事件中保存和加载视图状态。由于要保存状态的页面具有公共基类,因此可以执行以下操作:
protected void Page_LoadComplete(object sender, EventArgs e)
{
//Set anything to the viewstate for accessing on a later postback
ViewState["Anything"] = 1;
if (Page.IsCallback)
{
//Persist the page state manualy (not needed on normal postback)
InvokeAspNetStateSaver();
}
...
}
protected override object SaveViewState()
{
object state = base.SaveViewState();
// your custom save logic
}
protected override void LoadViewState(object savedState)
{
object state = // load your view state here
base.LoadViewState(savedState);
}
不同的问题是,将状态存储在某个地方是否是一个好的设计。最终得到了它
事情是这样的
在对页面
类(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()
负责加载页面状态,它执行每个回发请求
方法SaveAllState()
负责保存页面状态。ASP.NET按以下代码执行:
if (this.IsCallback)
{
this.RenderCallback();
}
else
{
...
this.SaveAllState();
...
}
这就是我的ViewState
无法在回调请求中保存的原因
所以,最后,解决方案!使用反射手动调用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);
}
谢谢你的回答。当.NET Framework是回调请求时,它不会保存状态。因此,不会调用SaveViewState方法(仅当它是正常回发时)。它应该是调用保存它的.NET Framework方法的某种方式。我只是不知道它到底在哪里。也许你可以在页面生命周期的某个时候,在你的回调请求中手动调用SaveViewState方法。这有点像黑客。最好使用会话或完整回发。在以后需要更改代码时,这种黑客行为可能代价高昂。