解決ASP.NET Web API Json對象迴圈參考錯誤

來源:互聯網
上載者:User

標籤:

前言

一般我們在開法 ASP.NET Web API 時,如果是使用 Entity Framework 技術來操作資料庫的話,當兩個 Entity 之間包含導覽屬性(Navigation Property)時,而當我們輸出的格式為 JSON 對象時,會出現一個例外,錯誤訊息為:「‘ObjectContent`1‘ 類型無法序列化內容類型 ‘application/json; charset=utf-8‘ 的回應主體。」,而小弟參考了 Will 保哥以及 Bruce 兩位前輩的文章後,整理出兩種小弟覺得比較可行的替代與解決方案。

瞭解問題

 

 

這張圖裡包含了兩張資料表 Orders 與 Order_Details ,兩者之間存在著一對多的關係,而預設 Entity Framework 會自動幫我們的關聯資料表加入導覽屬性(Navigation Property),接著我們往下一張圖看下去:

        public IEnumerable<Orders> GetOrders()         {             return db.Orders;         }

這段程式碼為 ValuesController 裡的一個 Function ,當我們請求時會返回 Orders 所有資料,但當我們輸入網址 /api/Values/ 請求時卻發生了這樣的錯誤:

   

這個問題發生的原因為,當我們請求某個特定的 Enity 時會取出該 Entity 的所有屬性內容,當然包誇了導覽屬性的資料,而究竟這個問題如何照成呢?以目前的案例來看,當我們取得 Orders 的資料時也會一併取得其導覽屬性,也就是 Order_Details 的所有資料,而在 Order_Details 裡也包含著 Orders 的導覽屬性,所以又會在去取得 Orders 的資料....,這樣兩個實體之間不停的往返就會造成了無限迴圈,也是我們前面所說的迴圈參考的錯誤。

如何解決

方法一:

在開發 ASP.NET MVC 中,時常會用到部分類別(Partail Class)來為我們的資料域位加上驗證屬性,所以利用此特性來解決我們的問題,首先在 Model 資料夾底下新增兩個檔案分別為:OrdersMetadata.cs 、Order_DetailsMetadata.cs

view sourceprint? 01. OrdersMetadata.cs 02.    03.      [MetadataType( typeof (OrderMD))] 04.      public partial class Order 05.      { 06.          public class OrderMD 07.          { 08.              [JsonIgnore()] // 需引用 using Newtonsoft.Json; 09.              public virtual ICollection<Order_details> Order_Details { get ; set ; } 10.          } 11.      }Order_DetailsMetadata.cs 12.    13.      [MetadataType( typeof (Order_DetailsMD))] 14.      public partial class Order_Details 15.      { 16.          public class Order_DetailsMD 17.          { 18.              [JsonIgnore()]  // 需引用 using Newtonsoft.Json; 19.              public virtual Orders Orders { get ; set ; } 20.          } 21.      }

這邊我們在在對應的導覽屬性上都加上 「JsonIgnore」的屬性,來防止迴圈參考的問題發生,記得是有關聯的兩邊都要加上「JsonIgnore」的屬性。

方法二:

另外一種方法則是利用我們在開發 ASP.NET MVC 時常用到的 ViewModel 的概念,針對特定的頁面或請求只返回特定的資料,所以這邊我們能透過 DTO 方式來解決我們問題,首先我們先在 Model 底下新增一個 DTO.cs 檔案: www.it165.net

DTO.cs

view sourceprint? 01. public class OrderDTO 02. { 03.      public int OrderID { get ; set ; } 04.      public string CustomerID { get ; set ; } 05.      public int ? EmployeeID { get ; set ; } 06.      public DateTime? OrderDate { get ; set ; } 07.      public List<Order_detailsDTO> Order_Detail { get ; set ; } 08. } 09. public class Order_DetailsDTO 10. { 11.      public int OrderID { get ; set ; } 12.      public decimal UnitPrice { get ; set ; } 13.      public decimal Quantity { get ; set ; } 14. }

並且修改我們原本在 Web API Controller 裡的 Function:

view sourceprint? 01. public IEnumerable<OrderDTO> GetOrders() 02. { 03.      NorthwindEntities db = new NorthwindEntities(); 04.       05.      return db.Orders.ToList().Select(p => new OrderDTO 06.      { 07.          CustomerID = p.CustomerID, 08.          EmployeeID = p.EmployeeID, 09.          OrderDate = p.OrderDate, 10.          OrderID = p.OrderID, 11.          Order_Detail = p.Order_Details.Select(x => new Order_DetailsDTO 12.          { 13.              OrderID = x.OrderID, 14.              Quantity = x.Quantity, 15.              UnitPrice = x.UnitPrice 16.          }).ToList() 17.      }); ; 18. }

總結

兩種作法都能解決造成迴圈對象參考的問題,而在 Bruce 和 Will 保哥的文章都指出用第一種方法來解決此迴圈參考錯誤是最正確的作法,兩種作法算是兩種不同的出發點,所以該怎麼用應該就是看各位讀者如何應用了。

解決ASP.NET Web API Json對象迴圈參考錯誤

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.