我們之前有個專案是用 ASP.NET MVC 1.0 開發,原本大家都是用 Visual Studio 2008 在開發,但上個月有位同事將專案升級至 Visual Studio 2010,升級的過程並沒有發生任何問題,不過他有把 ASP.NET MVC 組件還原成 1.0 的版本,過了一個月後終於在測試機身上爆發問題,我今天也是查了十幾分鐘才找到問題發生的主因。
首先,我們用 Visual Studio 2010 開啟 ASP.NET MVC 1.0 專案時在 Visual Studio 轉換精靈 的最後一步確定沒有升級到 .NET Framework 4 版,即便如此,Visual Studio 轉換精靈 預設還是會將 ASP.NET MVC 專案所有設定都改成 2.0 版:
對從 ASP.NET MVC 1.0 升級到 2.0 的專案來說,最需要注意的地方就是兩個 Web.config 檔,分別是:
- 網站根目錄\Web.config
- 網站根目錄\Views\Web.config
這兩個檔案中與 ASP.NET MVC 有關的地方全部都會修改成類似如下的設定(以下僅其中一段範例)
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
namespace="System.Web.Mvc" tagPrefix="mvc" />
另外一個重點是網站根目錄下的 Web.config 裡的 <runtime> 設定,其中定義了 assemblyBinding 會讓網站裡所有用到 ASP.NET MVC 1.0 的組件參考全部都轉向到 ASP.NET MVC 2.0 的組件:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
基本上 ASP.NET MVC 2.0 與 1.0 的相容性很高,但是 Model Binding 的驗證改的比較多一些 ( 從 Input Validation 改成 Model Validation ),像我們 ASP.NET MVC 1.0 的案子就有用到許多 Input Validation 機制,所以必須將升級 2.0 之後的專案再改回 1.0 版,不過當時將專案升級的同事並沒有發現這些細節,沒有修改到 Web.config 的設定,而單單只將專案 bin 目錄下的 System.Web.Mvc.dll 組件還原成 1.0.0.0 的版本而已。
因為這樣子直接替換檔案在開發環境並沒有問題發生,所以也不以為意,而事實上在開發環境的專案一直在用註冊在 GAC 的 System.Web.Mvc.dll 組件 (2.0.0.0),但有趣的是正式機從來沒掛掉過,那是因為正式機每次更版都不會直接覆蓋 Web.config 檔,所以設定檔完全沒動過,因此都沒發生過問題。
最近在架設另一台測試機時,由於是全新的環境,也沒有另外安裝 ASP.NET MVC 2.0 組件,所以 GAC 並沒有註冊任何 ASP.NET MVC 組件,因此網站在執行 ASP.NET MVC 時就確定是讀取 bin 目錄下的 System.Web.Mvc.dll 組件 (1.0.0.0) 了,因此在安裝好網站後出現的錯誤畫面卻是:
各位看倌!這是什麼機車的錯誤阿~ 看到這個錯誤,看到這種錯誤根本不可能聯想到組件版本的問題阿!
接下來我的腦中出現的判斷順序是:
- 檔案真的不存在嗎?
( 不可能,因為程式都是從本地端複製上去的,雙重驗證之後也已排除此問題 )
- 檔案目錄是否因為權限不足以致於 IIS/ASP.NET 無法讀取該檔案?
( 使用 Process Monitor 驗證存取權限問題,確認檔案有被正常讀入 )
注意: 切勿因為無法修復問題而任意將目錄權限修改為 Everyone 完全控制
- 清空 Temporary ASP.NET Files 目錄下所有資料
( 重新編譯依然無效,問題依然無法解決 )
- 回收應用程式集區
( 開始在瞎測了 )
- 重啟 IIS
( 瞎子摸象,準備啟動 3R 策略,不過依然失效 )
[ 註: 這裡的 3R 是指 Recycle , Restart , Reinstall,若是 Reboot 也經常有人使用 ]
檢查到這裡,我都還沒想到是 ASP.NET MVC 版本的問題,即便上 Google 查詢也查不到有相關的解決方案,最後才想到去看一下組件版本是不是與 Web.config 相符合。
結果真是這個問題耶!
最後把 Views\Web.config 裡的組件編號全部修改成 1.0.0.0 就修復了這個問題:
<pages
validateRequest="false"
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<controls>
<add assembly="System.Web.Mvc, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
namespace="System.Web.Mvc" tagPrefix="mvc" />
</controls>
</pages>
除錯,真的是一門學問,還需要創意加持!
相關連結