我曾介紹過App_Data好用的隱身特性,今天同事傳給我一則MSDN討論,提到App_Data的檔案更動會造成Web Application重新啟動,讓我大吃一驚,因為手邊有幾個專案會在App_Data寫入Log檔,時機還挺頻繁的,若一變動檔案就重啟,網站應該早就爆炸身亡了才對?

爬了文,結論是: "更動App_Data**有可能**導致AppDomain重啟! 如果App_Data下有子目錄被刪除的話"。主要參考來源是Lady Debugger, Tess, 的這篇文章:

An application domain will unload when any one of the following occurs:

  • Machine.Config, Web.Config or Global.asax are modified
  • The bin directory or its contents is modified
  • The number of re-compilations (aspx, ascx or asax) exceeds the limit specified by the <compilation numRecompilesBeforeAppRestart=/> setting in machine.config or web.config (by default this is set to 15)
  • The physical path of the virtual directory is modified
  • The CAS policy is modified
  • The web service is restarted
  • (2.0 only) Application Sub-Directories are deleted (see Todd’s blog http://blogs.msdn.com/toddca/archive/2006/07/17/668412.aspx for more info)

為了安心起見,我還是寫了個程式驗證: (ASP.NET 3.5 on IIS7)

<%@ Page Language="C#" %>
<script runat="server">
    const string SESS_KEY = "MySessVal";
    const string DIR_NAME = "TestDir";
    const string FILE_NAME = "TestFile.txt";
    void btnRead_Click(object sender, EventArgs e)
    {
        lblSessValue.Text = (string)Session[SESS_KEY];
    }
    protected void btnSave_Click(object sender, EventArgs e)
    {
        Session[SESS_KEY] = Guid.NewGuid().ToString();
        btnRead_Click(sender, e);
    }
    protected void btnCreateDir_Click(object sender, EventArgs e)
    {
        System.IO.Directory.CreateDirectory(
            Server.MapPath("~/App_Data/" + DIR_NAME));
        btnRead_Click(sender, e);
    }
    protected void btnDelDir_Click(object sender, EventArgs e)
    {
        System.IO.Directory.Delete(
            Server.MapPath("~/App_Data/" + DIR_NAME));
        btnRead_Click(sender, e);
    }
    protected void btnWriteFile_Click(object sender, EventArgs e)
    {
        System.IO.File.WriteAllText(
            Server.MapPath("~/App_Data/" + FILE_NAME), "AAA");
        btnRead_Click(sender, e);
    }
    protected void btnDelFile_Click(object sender, EventArgs e)
    {
        System.IO.File.Delete(Server.MapPath("~/App_Data/" + FILE_NAME));
        btnRead_Click(sender, e);
    }
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>App_Data重啟WebApp測試</title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:Label Text="" ID="lblSessValue" runat="server" EnableViewState="false" />
    <hr />
    <asp:Button ID="btnSave" runat="server" Text="存入Session" 
        onclick="btnSave_Click" />
    <asp:Button ID="btnRead" runat="server" Text="讀取Session" 
        onclick="btnRead_Click" />
    <asp:Button ID="btnCreateDir" runat="server" Text="建立目錄" 
        onclick="btnCreateDir_Click" />
    <asp:Button ID="btnDelDir" runat="server" Text="刪除目錄" 
        onclick="btnDelDir_Click" />
    <asp:Button ID="btnWriteFile" runat="server" Text="寫入檔案" 
        onclick="btnWriteFile_Click" />
    <asp:Button ID="btnDelFile" runat="server" Text="刪除檔案" style="height: 26px" 
        onclick="btnDelFile_Click" />
    </form>
</body>
</html>

按下【存入Session】會產生一個GUID存入Session中,之後可以按【建立目錄】、【刪除目錄】、【寫入檔案】、【刪除檔案】,接著按【讀取Session】可以觀察Session保存的值是否消失。

實驗證明了只有【刪除目錄】會導致Session消失,特此筆記。

【2014-12-01更新】ASP.NET 4+放寬了重啟Web Appliation的觸發條件:(感謝網友無名回饋)
In ASP.NET 4 the rules around restarting appdomains was relaxed. It is possible to create folders and delete folders in ASP.NET 4 applications without recyling the appdomain. However there are exceptions. Any directory structure that is known to ASP.NET and that contains globally referenced compiled artifacts will still cause appdomain recycles when the folder contents change. For example creating and deleting folders and files inside of the /bin directory will still trigger appdomain recycles. 參考


Comments

# by Rex

好像不只App_Data, 整個web site範圍內好像都會...

# by 大估

我記得也是整個WEB SITE範圍內都會影響… 之前在網站目錄下建了一個FILE_UP目錄,裡面再依各單據建立子目錄,功能上線後半年,多寫了一個自動刪三個月前建立的目錄的功能,結果,常常有人反應網頁操作到一半,就被踢出來(session timeout),後來才想起來這件事… 後來,把FILE_UP的目錄移出WWWROOT目錄,就又正常了…

# by Jeffrey

to Rex, 大估,WebApp其他目錄下因為會有與ASP.NET程式本身相關的東西,變更後需要重新編譯較易理解。App_Data較讓我意外是因為底下的東西理論上都是純資料,與程式編譯應無關聯,之前倒沒想到它也會導致AppDomain重啟。

# by 小銘

你好,搜尋相關問題,來到你的Blog 這問題除了將App_Data下須修改的資料夾搬移到其他目錄儲存,不知道是否還有其他處裡方式呢。

# by Jeffrey

to 小銘, App_Data下的子目錄被刪除時會導致AppDomain重啟看來是ASP.NET的特性,我想要避免就只能將資料夾移到Web之外囉。

# by 無名

今日同樣程式碼 在 IIS 7.5 以 ASP.net 4.5 測試,已經沒有 '【刪除目錄】會導致Session消失' 的這種現象。(亦 App_Data 資料夾下,執行【建立目錄】、【刪除目錄】、【寫入檔案】、【刪除檔案】動作,不會出現導致Session消失現象)

# by Jeffrey

to 無名,謝謝回饋!剛才查了資料,確實自ASP.NET 4.0起有了改變,已加入本文。

Post a comment