昨天在Web上遇到以下的錯誤:

Event message: A compilation error has occurred. Exception type: HttpCompileException

Exception message: c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\MyApp\868561b0\194f3b40\App_Web_datawriter.aspx.d119a6e4.lfyr98zw.0.cs(106): error CS0433: The type 'Darkthread.Common.DataWriter' exists in both 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\itrq\868561b0\194f3b40\assembly\dl3\f1f147bd\ee5abd33_e17cc701\DRARWeb.Folder1.DLL' and 'c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\itrq\868561b0\194f3b40\assembly\dl3\28ccdec0\9f367833_e17cc701\DARKWeb.Folder2.DLL'

錯誤發生的時機是使用者呼叫Folder1\DataWriter.aspx時,系統傳回了物件名稱重覆的問題。追了一下,原來問題是這麼發生的:

在ASP.NET 1.1時代,我寫了一個DataWriter網頁,在過去的專案模式下,元件預設會用Folder名稱宣告成結構化的命名空間(Namespace),它被放在Darkthread Web Application的Common目錄下,因此理所當然Class Name就是Darkthread.Common.DataWriter。

在一個ASP.NET 2.0專案中,我將這個1.1時代的DataWriter.aspx搬到Folder1與Folder2底下改寫出兩個網頁。VS 2005在新增網頁時預設會將兩個網頁的CodeBeside Class命名為Folder1_DataWriter及Folder2_DataWriter,所以不會有名稱重覆的問題。而由外面Copy過來的ASPX,VS 2005則保留了原來的Class Name。此時就出現危機了: Folder1/DataWriter.aspx與Folder2/DataWriter.aspx的Code Beside Class,名字都叫做Darkthread.Common.DataWriter。

不過炸彈並不會馬上爆炸,在Debug與測試階段,Web Site Project的.cs會獨立即時編譯,因此不會有撞名的情況。等到我們使用Web Deployment Project並選擇每顆Folder Build成一顆DLL時,由於兩個同名Class分屬不同的DLL(Folder1.dll及Folder2.dll),所以編譯及部署時也不會發生錯誤。真正炸彈引爆的時機是當我們呼叫Folder1/DataWriter.aspx或Folder2/DataWriter.aspx時,由於BIN下有兩個DLL包含相同名稱的Class,ASP.NET不知要載入哪一顆,就導致了前述的HttpComplieException。

【結論】
由其他地方拖入ASPX檔案時,記得要更改Class Name以避免重覆。至於要怎麼檢查Web Deployment Project中有沒有重覆的類別名稱? 我想到最簡單的方法是先將Web Deployment Project的設定改成Build成單一DLL(如下圖),此時如果Build時出現"aspnet_merge.exe" exited with code 1.的錯誤訊息,多半就代表Project中有Class名稱重覆的問題,去找出來吧! (如果專案很大,尋人的難度直追阿亮的超級任務,多半得靠始作俑者的記憶追查,不知有沒有其他更簡便的方法? 還是該寫台潛盾機?)

補充: 關於Web Deployment Project的使用說明,可以參考文章-ASP.NET 2.0專案部署問題研究


Comments

# by Kimmy

到﹝工具﹞→﹝選項﹞ 裡面的 ﹝專案和方案﹞→﹝﹝建置並執行﹞ 裡面,將「MSBuild 專案建置輸出詳細等級」選擇「詳細」,即可在建置時得到更精細的說明了呢。

Post a comment