開發自定義控件時,遲早會遇到複雜類型屬性的 ViewState 持久化問題。本文通過一個「丈夫-妻子」的經典案例,展示直接存放自定義物件導致的序列化異常,並指出單純加 [Serializable] 的隱患。
namespace Controls {
using System;
using System.Web.UI;
public class Husband : Control {
public Wife MyWife {
get { /* ... */ }
set { ViewState["MyWife"] = value; }
}
}
public class Wife {
private string m_Name;
private int m_Age;
public string Name { get { return m_Name; } set { m_Name = value; } }
public int Age { get { return m_Age; } set { m_Age = value; } }
}
}
運行時拋出異常:
Type 'Controls.Wife' in Assembly 'Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
雖然標記 [Serializable] 可暫時解決錯誤,但 ViewState 內部使用 LosFormatter 進行二進制序列化,要求類型具備完整的序列化契約。若類別包含不可序列化的成員(如事件委派、非托管資源),仍會在運行時失敗。此外,ViewState 儲存體積會隨物件圖複雜度膨脹,影響頁面效能。
ASP.NET 提供兩種標準路徑:
IStateManager,自行控制 LoadViewState/SaveViewState/TrackViewState。[TypeConverter],利用字串轉換機制在 ViewState 中以字串形式保存(見系列二)。自定義類型進入 ViewState 前,務必確保其可正確序列化且體積可控。下一篇將示範 TypeConverter 的完整實作細節。