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

由於我們有個專案已經升級至 .NET 4.0，而我希望在開發時期要將 [ASP.NET MVC 2.0 RTM 原始碼](https://web.archive.org/web/20171101223000/http://aspnet.codeplex.com:80/releases/view/41742)連同原專案一起開發，其實在不更動 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)' 時違反繼承安全性規則。覆寫方法的安全性存取範圍必須符合被覆寫方法的安全性存取範圍。](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/8a8b8b4397539b275466-image_thumb_23.png "System.TypeLoadException: 覆寫成員 'System.Web.Mvc.TempDataDictionary.System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo, System.Runtime.Serialization.StreamingContext)' 時違反繼承安全性規則。覆寫方法的安全性存取範圍必須符合被覆寫方法的安全性存取範圍。")](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/8c9fb8ba6439f71c7945-image_161.png)

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

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](http://msdn.microsoft.com/en-us/library/system.typeloadexception.aspx) 有關，也就是執行到某一個 Method 的時候由於無法載入另一個型別而導致引發 [System.TypeLoadException](http://msdn.microsoft.com/en-us/library/system.typeloadexception.aspx) 例外狀況。

這時我們再從錯誤訊息上所提示的型別進行追查，找到 [TempDataDictionary 類別](http://msdn.microsoft.com/en-us/library/system.web.mvc.tempdatadictionary.aspx)定義的地方，我們可以利用 Visual Studio 2010 的 **巡覽至** ( **Navigate To** ) 功能 ( 可按 **Ctrl + ,** 快速鍵開啟 ) 並輸入 [TempDataDictionary](http://msdn.microsoft.com/en-us/library/system.web.mvc.tempdatadictionary.aspx) 即可搜尋到，如下圖示（點圖可放大）：：

[![Visual Studio 2010 的 巡覽至 ( Navigate To ) 功能](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/1950db1f50003796284e-image_thumb_24.png "Visual Studio 2010 的 巡覽至 ( Navigate To ) 功能")](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/70bcc34bbc829e9ad1c5-image_162.png)

我先看到 [TempDataDictionary 類別](http://msdn.microsoft.com/en-us/library/system.web.mvc.tempdatadictionary.aspx)的第一行有實做 [ISerializable 介面](http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx)

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

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

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

接著便找到此類別有實做 [ISerializable 介面](http://msdn.microsoft.com/en-us/library/system.runtime.serialization.iserializable.aspx)的 GetObjectData(…) 方法：

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

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

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

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

    ![](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/2d7c54a336a09e079efe-image_163.png)

2\. 在此檔案最後一行加上一個組件層級的 [System.Security.SecurityRules](http://msdn.microsoft.com/en-us/library/system.security.securityrulesattribute.aspx) 屬性，並設定 Level1 參數

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

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

**結語**

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

**相關連結**

-   [aspnet - Release: ASP.NET MVC 2 RTM](https://web.archive.org/web/20171101223000/http://aspnet.codeplex.com:80/releases/view/41742) ( Source Code )
-   [ASP.NET MVC 開發心得分享 (2)：與原始碼共舞](/post/2009/02/08/ASPNET-MVC-Developer-Note-Part-2.aspx)
-   [TypeLoadException based on Security-Transparent Code, Level 2](https://weblogs.asp.net/peterblum/typeloadexception-based-on-security-transparent-code-level-2)
-   [Inheritance security rules violated while overriding member error. MVC 2.0 and Runtime .Net 4](https://web.archive.org/web/20100817062642/http://aspnet.codeplex.com:80/workitem/6195)
-   [程式碼存取安全性](http://msdn.microsoft.com/zh-tw/library/c5tk9z76.aspx) ( .Net Framework 4 )
-   [What's New in the .NET Framework 4](http://msdn.microsoft.com/en-us/library/ms171868.aspx)
-   [Security Changes in the .NET Framework 4](http://msdn.microsoft.com/en-us/library/dd233103.aspx)
-   [Security-Transparent Code, Level 1](http://msdn.microsoft.com/en-us/library/bb397858.aspx)
-   [Security-Transparent Code, Level 2](http://msdn.microsoft.com/en-us/library/dd233102.aspx)
