ASP.NET 2.0 預設監視應用程式目錄下所有檔案/資料夾變更。刪除資料夾會觸發 FileChangesMonitor,導致 AppDomain 重啟,進而清空 In-Process Session、Cache、Application 狀態,使用者被強制登出。
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() { }
}
}
<system.web>
<httpModules>
<add name="StopAppDomainRestartOnFolderDelete"
type="MyWebsite.StopAppDomainRestartOnFolderDeleteModule" />
</httpModules>
</system.web>
效果:刪除資料夾不再觸發 AppDomain 重啟;修改 web.config、bin 目錄仍會正常重啟 (符合預期)。
若專案頻繁建立/刪除資料夾,或需多伺服器共享 Session,建議將 Session 狀態移至獨立程序:
<system.web>
<sessionState mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="20" />
</system.web>
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\Port 修改[Serializable]| 方案 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| HttpModule 停止子目錄監視 | 零程式碼變更、In-Process 效能最好、部署簡單 | 使用 Reflection 存取私有成員,未來 .NET 版本可能失效;單機限制 | 單機部署、偶爾刪除資料夾、不想改架構 |
| StateServer | 跨 AppDomain/進程/機器共享 Session、支援 Web Farm、重啟不丟 Session | 網路延遲、序列化開銷、需額外維護 State Service | Web Farm、頻繁部署/回收、需高可用 Session |
| SQLServer 模式 | 持久化、可查詢、支援叢集 | 效能最差、需 SQL Server 授權 | 極高可用性需求、需審計 Session 內容 |
HttpRuntimeSection.FcnMode 設定 Disabled 或 NotSet 更優雅地控制監視行為 (需 IIS 7.5+)。