2

问题是,我需要在请求ViewState期间坚持。CallBack

我知道当请求是CallBack. 所以,我需要一个替代方案来使它工作。

ASP.NET 应用程序有一个自定义PageStatePersister,它将所有 Page State( ViewState) 存储到Session. 这种方式ViewState不会在任何时候发送/检索到客户端(尽管隐藏字段仍然存在于页面上,但没有价值)。ViewState不必在响应中返回,CallBack我只需要以某种方式调用ViewState在正常PostBack请求中保存的机制。

它会是这样的:

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();
    }
    ...
}

感谢你的帮助。

4

2 回答 2

2

终于明白了。

事情就是这样。

在对Page类(System.Web.UI以下代码是 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);
}

MethodLoadAllState()负责加载页面状态,它执行每个 PostBack 请求。

MethodSaveAllState()负责保存页面状态。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);
}
于 2012-10-26T16:10:19.150 回答
0

可以在页面上的 SaveState 和 LoadState 事件中保存和加载视图状态。由于您有页面的通用基类,您想要在其中保存状态,您可以执行以下操作:

    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);
    }

不同的问题是,将状态存储在某处是否是好的设计。

于 2012-10-24T12:37:37.283 回答