預設 ViewState 經 Base64 編碼置於隱藏欄位 __VIEWSTATE,隨頁面往返傳輸,導致頻寬浪費、載入緩慢、安全風險。ASP.NET 允許透過繼承 PageStatePersister 將 ViewState 存至 **Cache、Session、Database、檔案** 等伺服器端介質,僅在頁面保留極小的 Token。
public abstract class PageStatePersister
{
public PageStatePersister(Page page) { ... }
public abstract void Save(); // 序列化並持久化 ViewState + ControlState
public abstract void Load(); // 反序列化還原
protected IStateFormatter StateFormatter { get; } // 內建 Base64 序列化器
public Page Page { get; }
}
protected override PageStatePersister PageStatePersister
{
get { return new SessionPageStatePersister(this.Page); }
}
ViewState 存入 Session,適合小型應用、單伺服器。叢集環境需 Session 共享 (StateServer/SQLServer/Redis)。
public class CachePageStatePersister : PageStatePersister
{
public CachePageStatePersister(Page page) : base(page) { }
public override void Save()
{
string key = "VS_" + Page.Session.SessionID + "_" + Page.Request.Path;
// 儲存 Pair(ViewState, ControlState)
var state = new Pair(ViewState, ControlState);
string serialized = StateFormatter.Serialize(state);
HttpRuntime.Cache.Insert(key, serialized, null,
DateTime.Now.AddMinutes(20), TimeSpan.Zero);
// 頁面僅保留 Token
Page.ClientScript.RegisterHiddenField("__VIEWSTATE_TOKEN", key);
}
public override void Load()
{
string key = Page.Request.Form["__VIEWSTATE_TOKEN"];
if (string.IsNullOrEmpty(key)) return;
string serialized = HttpRuntime.Cache[key] as string;
if (serialized != null)
{
var state = (Pair)StateFormatter.Deserialize(serialized);
ViewState = state.First;
ControlState = state.Second;
}
}
}
頁面繼承:
protected override PageStatePersister PageStatePersister
{
get { return new CachePageStatePersister(this); }
}
| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 隱藏欄位 (預設) | 零配置、無狀態 | 頻寬大、Base64 可解碼 | 簡單頁面、ViewState 小 |
| Session | 內建、簡單 | Session 記憶體壓力、序列化成本 | 中小應用、單機/共享 Session |
| Cache (自訂) | 可控過期、不佔 Session、高效能 | 需管理 Key、叢集需分散式 Cache | 高流量、大 ViewState、叢集 (Redis) |
| Database | 持久、可審計、跨伺服器 | I/O 開銷大 | 合規要求、超長壽命 ViewState |
<pages enableViewStateMac="true" viewStateEncryptionMode="Auto" /> (預設開啟)。StateFormatter 保護 (MAC + 加密)。合理導向 ViewState 儲存位置,能顯著降低頻寬、提升首屏速度、增強安全性。