The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

ASP.NET MVC 開發心得分享 (20):與原始碼共舞 ( .NET 4.0 )

由於我們有個專案已經升級至 .NET 4.0,而我希望在開發時期要將 ASP.NET MVC 2.0 RTM 原始碼連同原專案一起開發,其實在不更動 System.Web.Mvc 專案的目標 Framework 為 3.5 的情況下是可以正常運作的,不過若像我們遇到一些比較特殊的情況可能會希望連 System.Web.Mvc 專案的目標 Framework 一併升級到 .NET 4.0,雖然升級後可以正常編譯,但是卻會在執行時期發生錯誤,以至於根本無法進行除錯,這時就必須動點小手腳才能讓 ASP.NET MVC 網站成功執行。

執行時出現的錯誤訊息為:

System.TypeLoadException: 覆寫成員 'System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' 時違反繼承安全性規則。覆寫方法的安全性存取範圍必須符合被覆寫方法的安全性存取範圍。

其圖示如下(點圖可放大):

System.TypeLoadException: 覆寫成員 'System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' 時違反繼承安全性規則。覆寫方法的安全性存取範圍必須符合被覆寫方法的安全性存取範圍。

另外抓出英文的錯誤訊息如下:

System.TypeLoadException: Inheritance security rules violated while overriding member: 'System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)'. Security accessibility of the overriding method must match the security accessibility of the method being overriden.

由錯誤訊息提供的行數來看比較難以進行偵錯,但從錯誤訊息可以得知一些線索,首先可以從這次引發的例外型別可以知道這跟 System.TypeLoadException 有關,也就是執行到某一個 Method 的時候由於無法載入另一個型別而導致引發 System.TypeLoadException 例外狀況。

這時我們再從錯誤訊息上所提示的型別進行追查,找到 TempDataDictionary 類別定義的地方,我們可以利用 Visual Studio 2010 的 巡覽至 ( Navigate To ) 功能 ( 可按 Ctrl + , 快速鍵開啟 ) 並輸入 TempDataDictionary 即可搜尋到,如下圖示(點圖可放大)::

Visual Studio 2010 的 巡覽至 ( Navigate To ) 功能

我先看到 TempDataDictionary 類別的第一行有實做 ISerializable 介面

public class TempDataDictionary : IDictionary<string, object>, ISerializable

而且錯誤訊息裡也有類似字眼:

System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable

接著便找到此類別有實做 ISerializable 介面的 GetObjectData(…) 方法:

protected virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
info.AddValue(_tempDataSerializationKey, _data);
}

但是錯誤訊息卻是「違反繼承安全性規則」,還有「覆寫方法的安全性存取範圍必須符合被覆寫方法的安全性存取範圍」,還好之前在研究 ASP.NET 4.0 時有順便看到 Security Changes in the .NET Framework 4 文章,當時我並沒有很深入研究,不過至少知道在 .NET 4.0 的程式碼存取安全性 ( Code Access Security ) 有做出一些變更,主要的變化在於 Security-Transparent Code 的預設機制已經調整成 enforcement (詳見 Security-Transparent Code, Level 2. 說明)。

所以要克服無法執行的問題必須透過以下 3 個步驟進行修正:

1. 開啟 System.Web.Mvc 專案的 Properties\AssemblyInfo.cs 檔案

   

2. 在此檔案最後一行加上一個組件層級的 System.Security.SecurityRules 屬性,並設定 Level1 參數

[assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)]

3. 重新建置專案,網站即可正常執行。

 

結語

雖然 MSDN 上的 Security-Transparent Code, Level 1 文件有提到開發 .NET Framework 4 應用程式最好都使用 Level 2 transparency,不過要理解 程式碼存取安全性 ( Code Access Security ; CAS ) 雖然很重要,不過要能釐清所有 CAS 的細節還真的不是一件好玩的事,因為在一般 AP 開發上幾乎很少用到,但這些觀念對於撰寫 Framework 的開發人員就絕對不得不去深入探究了。

 

相關連結