| 方式 | 存儲位置 | 生命週期 | 數據類型 | 安全性 | 適用場景 |
|---|---|---|---|---|---|
| QueryString | URL | 單次請求 | 字符串 | 低 (明文可見) | 簡單參數、書籤分享、SEO |
| Session | 伺服器記憶體/StateServer/SQL | 會話期間 (可配置) | 任意物件 | 中 (需防劫持) | 用戶狀態、購物車、權限 |
| Cookie | 客戶端瀏覽器 | 過期時間可控 | 字符串 | 低 (可竄改/攔截) | 記住我、偏好設置、跨域追蹤 |
| Application | 伺服器記憶體 (全域) | 應用程式生命週期 | 任意物件 | 中 (全域可見) | 計數器、緩存、配置 |
| Server.Transfer | 伺服器內存 (請求上下文) | 單次請求鏈 | 任意物件 | 高 (不暴露客戶端) | 多步向導、表單分步、內部跳轉 |
| 隱藏字段 | 頁面表單 (ViewState) | 單次 PostBack | 字符串 | 中 (可加密) | 表單狀態保持、CSRF Token |
// 源頁面 a.aspx
Response.Redirect($"b.aspx?name={Server.UrlEncode(lblName.Text)}&id={userId}");
// 目標頁面 b.aspx
string name = Request.QueryString["name"]; // 自動解碼
int id = int.Parse(Request.QueryString["id"]);
缺點: 長度限制 (~2KB)、明文暴露、可被篡改、不支援複雜類型。
// 源頁面
Session["CurrentUser"] = userObj; // 存放任意物件
// 目標頁面
if (Session["CurrentUser"] is User u) { /* 使用 */ }
// 清理
Session.Remove("CurrentUser"); // 單個
Session.Clear(); // 全部
Session.Abandon(); // 銷毀會話
注意: 大量數據導致記憶體壓力,集群需配置 StateServer/SQLServer。
// 寫入
var cookie = new HttpCookie("Pref", "theme=dark&lang=zh") {
Expires = DateTime.Now.AddMonths(1),
HttpOnly = true, // 防 XSS
Secure = true // 僅 HTTPS
};
Response.Cookies.Add(cookie);
// 讀取
if (Request.Cookies["Pref"] != null) {
string val = Request.Cookies["Pref"].Value;
}
限制: 每域 ~4KB、數量限制、用戶可禁用/清除。
// 寫入 (需鎖定防併發)
Application.Lock();
Application["VisitCount"] = (int)Application["VisitCount"] + 1;
Application.UnLock();
// 讀取
int count = (int)Application["VisitCount"];
用途: 全站計數器、緩存公共配置、應用級單例。切勿存放用戶私有數據!
// 源頁面 a.aspx - 定義公共屬性
public string UserName => txtName.Text;
// 跳轉
Server.Transfer("b.aspx", true); // true=保留 QueryString/Form
// 目標頁面 b.aspx - 獲取前頁實例
protected void Page_Load(object sender, EventArgs e) {
if (Context.Handler is a prevPage) {
string name = prevPage.UserName;
// 或直接取表單值
string email = Request.Form["txtEmail"];
}
}
與 Response.Redirect 差異:
| 特性 | Server.Transfer | Response.Redirect |
|---|---|---|
| 執行位置 | 伺服器端 | 客戶端 (302) |
| URL 變化 | 不變 | 變為新地址 |
| 可傳遞物件 | 是 (Context.Handler) | 否 (僅 QueryString) |
| 跨應用程式 | 否 (同虛擬目錄) | 是 (任意 URL) |
| 瀏覽器歷史 | 無記錄 | 有記錄 |
| 相對路徑資源 | 可能錯誤 | 正常 |
// 前台
<asp:HiddenField ID="hfToken" runat="server" Value="<%= GenerateToken() %>" />
// 後台讀取 (PostBack 時)
string token = hfToken.Value;
本質是 <input type="hidden">,隨表單提交,配合 ViewState 加密可防篡改。
需要跨頁面傳值
│
├─ 數據敏感/複雜對象/會話級 → Session
│
├─ 簡單參數/需分享書籤/SEO → QueryString
│
├─ 客戶端持久化/跨會話/記住我 → Cookie
│
├─ 全站共享/計數/配置 → Application
│
├─ 內部多步流程/不想換 URL/傳對象 → Server.Transfer
│
└─ 單頁 PostBack 狀態/CSRF Token → 隱藏字段
cookieHttpOnly、regenerateExpiredSessionId、短超時HttpOnly、Secure、SameSite=Strict/Lax、簽名驗證「沒有最好的傳值方式,只有最適合場景的選擇。」—— 理解存儲位置、生命週期、類型支援、安全邊界五大維度,組合使用才能構建健壯的 Web 應用。