解决ASP.NET Web API Json对象循环参考错误

前言

一般我们在开法 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 保哥的文章都指出用第一种方法来解决此循环参考错误是最正确的作法,两种作法算是两种不同的出发点,所以该怎么用应该就是看各位读者如何应用了。

时间: 2024-10-05 10:16:37

解决ASP.NET Web API Json对象循环参考错误的相关文章

ASP.NET Web API 路由对象介绍

ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了一些微小的修改,这也是根据每个框架的特性来制定的,今天我们就来看一看路由的结构,虽然我在MVC系列里写过路由的篇幅不过在这里是Web API 路由对象介绍. ASP.NET Web API路由.管道 ASP.NET Web API 开篇介绍示例 ASP.NET Web API 路由对象介绍 ASP.

ASP.NET Web API WebHost宿主环境中管道、路由

ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境中ASP.NET Web API框架中的管道.路由又是哪一种形态. ASP.NET Web API路由.管道 ASP.NET Web API 开篇介绍示例 ASP.NET Web API 路由对象介绍 ASP.NET Web API 管道模型 ASP.NET Web API selfhost宿主环境

ASP.NET Web API 管道模型

ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是从消息管道经过的,这是必经之地,本篇就为大家简单的介绍一下ASP.NET Web API框架中的管道对象模型. ASP.NET Web API路由.管道 ASP.NET Web API 开篇介绍示例 ASP.NET Web API 路由对象介绍 ASP.NET Web API 管道模型 ASP.NE

How ASP.NET Web API 2.0 Works?[持续更新中…]

一.概述 RESTful Web API [Web标准篇]RESTful Web API [设计篇] 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用 二.路由 ASP.NET的路由系统:URL与物理文件的分离 ASP.NET的路由系统:路由映射 ASP.NET的路由系统:根据路由规则生成URL ASP.NET Web API路由系统的几个核心类型 Web Host下的URL路由 三.消息处理管道 ASP.NET Web API标准的"管道式"设计

Asp.Net Web API 2第十三课——ASP.NET Web API中的JSON和XML序列化

前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文描述ASP.NET Web API中的JSON和XML格式化器. 在ASP.NET Web API中,媒体类型格式化器(Media-type Formatter)是一种能够做以下工作的对象: 从HTTP消息体读取CLR(公共语言运行时)对象 将CLR对象写入HTTP消息体 Web API提供了用于JSON和XML的媒体类

ASP.NET Web API 2.1支持Binary JSON(Bson)

ASP.NET Web API 2.1内建支持XML.Json.Bson.form-urlencoded的MiME type,今天重点介绍下Bson. BSON是由10gen开发的一个数据格式,目前主要用于MongoDB中,是MongoDB的数据存储格式.BSON基于JSON格式,选择JSON进行改造的原因主要是JSON的通用性及JSON的schemaless的特性. BSON主要会实现以下三点目标: 1.更快的遍历速度 对JSON格式来说,太大的JSON结构会导致数据遍历非常慢.在JSON中,

使用Jil序列化JSON提升Asp.net web api 性能

JSON序列化无疑是Asp.net web api 里面性能提升最重要的一环. 在Asp.net web api 里面我们可以插入自定义的MediaTypeFormatter(媒体格式化器), 说白了就是根据HTTP content-type application/json 来判断采用哪种媒体格式化器 具体实现,记得要引入Jil包 public class JilFormatter : MediaTypeFormatter { private readonly Options _jilOpti

JSON Web Token in ASP.NET Web API 2 using Owin

In the previous post Decouple OWIN Authorization Server from Resource Server we saw how we can separate the Authorization Server and the Resource Server by unifying the "decryptionKey" and "validationKey" key values in machineKey node

&quot;Asp.Net Web Api MediaTypeFormatter Error for x-www-formurlencoded data&quot; 解决方法

遇到标题中所说的问题原因是使用 jQuery AJAX 以 POST 方式调用 Asp.Net Web API .解决办法请看以下代码中有注释的部分. public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Formatters.Clear(); config.Formatters.Add( new JsonMediaTypeFormatter { Seri