首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET 公共變數失效問題:正確使用 Session 管理使用者狀態

     編輯:ASP.NET 基礎

問題情境

在 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 狀態

Session 是伺服器端為每個使用者瀏覽器會話維護的字典,跨請求保存資料,生命週期預設 20 分鐘閒置逾時。

登入時寫入 Session

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();
        }
    }
}

Session 使用最佳實務

1. 封裝成強型別屬性

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,避免魔術字串散落各處。

2. 避免存放大型物件

  • Session 預設 In-Proc 模式存記憶體,大量資料會導致記憶體壓力。
  • 僅存放必要識別資訊(UserId、Role、Flag),完整物件改從資料庫或快取讀取。

3. 登出時清除

protected void btnLogout_Click(object sender, EventArgs e)
{
    Session.Clear();        // 清除所有 Session 資料
    Session.Abandon();      // 立即結束 Session
    FormsAuthentication.SignOut();
    Response.Redirect("Login.aspx");
}

4. Web Farm / Load Balancer 環境

若部署多台伺服器,必須將 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");
            }
        }
    }
}

總結

  • 頁面類別的實例欄位無法跨請求保存資料,ASP.NET 每次請求都會新建頁面實例。
  • Session 是最標準、最安全的跨請求狀態管理機制,適用於使用者識別、權限旗標、購物車等場景。
  • 封裝 Session 存取為強型別屬性,集中管理 Key 名稱與轉換邏輯,降低維護成本。
  • 注意 Session 模式設定、資料大小、登出清理與分散式部署需求。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved