【问题标题】:With ASP.NET viewstate, is there a best practice for when in the lifecycle to access the viewstate?使用 ASP.NET 视图状态,在生命周期中何时访问视图状态是否有最佳实践?
【发布时间】:2010-11-08 15:54:34
【问题描述】:

在构建自定义控件时,我看到了两种使用视图状态的模式。一种是使用属性将视图状态访问伪装成持久数据。

   public bool AllowStuff
   {
       get
       {
           return (ViewState[constKeyAllowStuff] != null) ?
               (bool)ViewState[constKeyAllowStuff] : false;
       }
       set { ViewState[constKeyAllowStuff] = value; }
   }

另一种是使用私有成员字段并覆盖控件上的Load/SaveViewState方法并显式处理:

 protected override object SaveViewState()
 {
     object[] myViewState = new object[2];
     myViewState[0] = base.SaveViewState();
     myViewState[1] = _allowStuff;
     return myViewState;
 }

 protected override void LoadViewState(object savedState)
 {
     object[] stateArray = (object[])savedState;
     base.LoadViewState(stateArray[0]);
     _allowStuff = (bool)stateArray[1];
 }

(为了清楚起见,我删除了很多安全检查,所以请忽略它。)

一种方法比另一种方法有什么特别的优势吗?我看不出它们在性能方面有何不同。版本 1 是懒惰的,所以如果您在通过期间不需要该特定值,我想您会节省一点。版本 1 也更抽象,更好地隐藏细节。第 2 版更清楚地说明数据何时真正有效并且可以读取或修改(在加载和保存之间),因为它更清楚地在 ASP.NET 生命周期内工作。

虽然版本 2 确实需要更多样板代码(属性、支持私有字段和在两个地方处理视图状态),但版本 1 将所有这些都组合到一个地方。

然后呢?

【问题讨论】:

    标签: asp.net viewstate


    【解决方案1】:

    私有成员字段方式常用于不直接访问 ViewState 状态包的对象。所以从某种意义上说,我将选项一用于自定义控件、用户控件或页面,或任何具有 ViewState 或类似属性的东西,但将另一个选项用于不直接访问 ViewState 的对象(如您希望能够“序列化”并存储在视图状态中的类)。例如,自定义控件将使用该方法来存储不直接引用视图状态的子对象的状态。

    HTH。

    【讨论】:

    • 在使用网络表单时,我总是遵循包装视图状态的属性模式,并在我的自定义 MVP 模式实现中传递该视图状态支持的属性。
    【解决方案2】:

    首先我会使用 ControlState 而不是 viewstate,因此如果在关闭视图状态的容器中它可以正常工作。

    然后我会覆盖 init、savecontrolstate、loadcontrolstate 和 databind。

    并确保注册该控件使用控件状态,即 Page.RegisterRequiresControlState(this)

    哦,优点是您的控件更健壮(用户不能轻易搞砸),并且在动态加载和跨回发“更好”时可以工作

    【讨论】:

    • 我可能应该更多地使用控制状态,但我觉得这样做很肮脏。就像我正在访问秘密的、无懈可击的视图状态。实际上,我们有时确实对您提到的内容存在问题,您的意思是说它对于动态加载和跨回发会更好地工作?
    • 基本上,我只是说如果你写得正确,它仍然可以工作,即使视图状态被关闭,即使它在更新面板中,或者有一个ajax回调等等..
    • 如果你知道你将成为 ajax 回调的一部分 ScriptManager sm = ScriptManager.GetCurrent(Page); if (sm == null) { throw new InvalidOperationException("此页面需要 ScriptManager"); } base.OnPreRender(e); ScriptManager.RegisterHiddenField(this, this.ClientStateID, "");
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 2012-04-19
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 2020-05-13
    • 1970-01-01
    相关资源
    最近更新 更多