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

ASP.NET 動態刪除資料夾導致 Session 遺失:HttpModule 解決方案與 StateServer 替代方案

     編輯:ASP.NET 基礎

問題根因

ASP.NET 2.0 預設監視應用程式目錄下所有檔案/資料夾變更。刪除資料夾會觸發 FileChangesMonitor,導致 AppDomain 重啟,進而清空 In-Process Session、Cache、Application 狀態,使用者被強制登出。

方案一:HttpModule 停止子目錄監視 (保留檔案/設定檔監視)

核心類別

using System.Reflection;
using System.Web;

namespace MyWebsite
{
    public class StopAppDomainRestartOnFolderDeleteModule : IHttpModule
    {
        public void Init(HttpApplication context)
        {
            // 取得 FileChangesMonitor 靜態屬性
            PropertyInfo p = typeof(HttpRuntime).GetProperty("FileChangesMonitor",
                BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
            object monitor = p.GetValue(null, null);

            // 取得 _dirMonSubdirs 欄位 (監視子目錄的物件)
            FieldInfo f = monitor.GetType().GetField("_dirMonSubdirs",
                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.IgnoreCase);
            object subdirMonitor = f.GetValue(monitor);

            // 呼叫 StopMonitoring() 停止子目錄監視
            MethodInfo m = subdirMonitor.GetType().GetMethod("StopMonitoring",
                BindingFlags.Instance | BindingFlags.NonPublic);
            m.Invoke(subdirMonitor, new object[] { });
        }

        public void Dispose() { }
    }
}

Web.config 註冊

<system.web>
  <httpModules>
    <add name="StopAppDomainRestartOnFolderDelete" 
         type="MyWebsite.StopAppDomainRestartOnFolderDeleteModule" />
  </httpModules>
</system.web>

效果:刪除資料夾不再觸發 AppDomain 重啟;修改 web.config、bin 目錄仍會正常重啟 (符合預期)。

方案二:改用 StateServer 模式外部化 Session (徹底解決)

若專案頻繁建立/刪除資料夾,或需多伺服器共享 Session,建議將 Session 狀態移至獨立程序:

<system.web>
  <sessionState mode="StateServer" 
                stateConnectionString="tcpip=127.0.0.1:42424" 
                stateNetworkTimeout="20" />
</system.web>
  • 需啟動 ASP.NET State Service (services.msc → ASP.NET State Service → 啟動)
  • 預設通訊埠 42424,可在註冊表 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\Port 修改
  • 序列化要求:存入 Session 的物件必須標記 [Serializable]

方案比較

方案優點缺點適用場景
HttpModule 停止子目錄監視 零程式碼變更、In-Process 效能最好、部署簡單 使用 Reflection 存取私有成員,未來 .NET 版本可能失效;單機限制 單機部署、偶爾刪除資料夾、不想改架構
StateServer 跨 AppDomain/進程/機器共享 Session、支援 Web Farm、重啟不丟 Session 網路延遲、序列化開銷、需額外維護 State Service Web Farm、頻繁部署/回收、需高可用 Session
SQLServer 模式 持久化、可查詢、支援叢集 效能最差、需 SQL Server 授權 極高可用性需求、需審計 Session 內容

驗證方式

  1. 登入網站,記下 SessionID
  2. 在後台程式動態建立並刪除資料夾
  3. 重新整理頁面,檢查 Session 是否保留、使用者是否仍登入

補充提醒

  • ASP.NET 4.5+ 可使用 HttpRuntimeSection.FcnMode 設定 Disabled 或 NotSet 更優雅地控制監視行為 (需 IIS 7.5+)。
  • 若使用 Azure Web Apps,預設即為外部 Session (Redis/Database),無此問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved