在 ASP.NET WebForms 專案中,開發人員常嘗試在頁面類別宣告 public int UserFlag = 0; 作為「公共變數」來區分使用者類型(如:一般註冊用戶 vs 信箱登入用戶)。然而,每次 HTTP 請求都會建立新的頁面實例,導致欄位數值無法跨請求保存,永遠重置為初始值。
public partial class LoginPage : System.Web.UI.Page
{
// 錯誤:這是實例欄位,每次 Request 都重新初始化
public int UserFlag = 0;
protected void btnEmailLogin_Click(object sender, EventArgs e)
{
UserFlag = 1; // 只有在這個 Request 存活
Response.Redirect("Profile.aspx"); // 新 Request -> 新 Page 實例 -> UserFlag 又變 0
}
}
Session 是伺服器端為每個使用者瀏覽器會話維護的字典,跨請求保存資料,生命週期預設 20 分鐘閒置逾時。
protected void btnEmailLogin_Click(object sender, EventArgs e)
{
// 驗證帳密...
if (ValidateUser(txtEmail.Text, txtPwd.Text))
{
// 將使用者類型標記存入 Session
Session["UserFlag"] = "1"; // 或存 int、enum、物件
// 導向需修改資料的頁面
Response.Redirect("EditProfile.aspx");
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// 安全取值:檢查 null 再轉型
string flag = Session["UserFlag"] as string;
if (flag == "1")
{
// 彈出修改提示、顯示特定 UI
ShowModifyProfileDialog();
}
}
}
public partial class BasePage : System.Web.UI.Page
{
protected UserType CurrentUserType
{
get
{
var val = Session["UserFlag"];
if (val == null) return UserType.Guest;
return Enum.TryParse(val.ToString(), out UserType t) ? t : UserType.Guest;
}
set => Session["UserFlag"] = value.ToString();
}
}
public enum UserType { Guest = 0, Registered = 1, EmailVerified = 2 }
所有頁面繼承 BasePage,即可直接使用 CurrentUserType,避免魔術字串散落各處。
protected void btnLogout_Click(object sender, EventArgs e)
{
Session.Clear(); // 清除所有 Session 資料
Session.Abandon(); // 立即結束 Session
FormsAuthentication.SignOut();
Response.Redirect("Login.aspx");
}
若部署多台伺服器,必須將 Session 模式改為 StateServer 或 SQLServer(web.config 設定),確保跨伺服器共享 Session。
<sessionState mode="SQLServer"
sqlConnectionString="Data Source=...;Initial Catalog=ASPState;..."
cookieless="false" timeout="20" />
| 方案 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| Session | 跨頁面、跨請求的使用者狀態 | 伺服器端安全、支援複雜物件、內建逾時管理 | 消耗伺服器記憶體、需設定分散式環境 |
| ViewState | 單一頁面多次 PostBack 保存控制項狀態 | 無伺服器資源、自動加密 | 增加頁面大小、不跨頁面 |
| Cookie | 長期記住使用者偏好、自動登入 Token | 客戶端儲存、跨 Session 保存 | 大小限制 4KB、用戶可刪除/竄改、需加密 |
| QueryString | 頁面間傳遞非敏感參數(如 ID、TabIndex) | 簡單、可書籤分享 | 可見、可竄改、長度限制、不適合敏感資料 |
| Cache / Application | 全域共享、唯讀、高頻存取資料 | 效能極佳、跨所有使用者 | 非使用者專屬、需自行處理同步與淘汰 |
public partial class Login : System.Web.UI.Page
{
protected void btnRegister_Click(object sender, EventArgs e)
{
// A 類型:註冊流程
Response.Redirect("Register.aspx");
}
protected void btnEmailLogin_Click(object sender, EventArgs e)
{
// B 類型:信箱登入
if (AuthenticateEmail(txtEmail.Text, txtPwd.Text))
{
// 關鍵:寫入 Session
Session["UserFlag"] = "1";
Session["UserEmail"] = txtEmail.Text;
Response.Redirect("EditProfile.aspx");
}
else
{
lblMsg.Text = "帳號或密碼錯誤";
}
}
}
public partial class EditProfile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// 關鍵:讀取 Session 判斷
if (Session["UserFlag"]?.ToString() == "1")
{
pnlModifyReminder.Visible = true;
lblEmail.Text = Session["UserEmail"]?.ToString();
}
else
{
Response.Redirect("Login.aspx");
}
}
}
}