解决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
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
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:
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对象循环参考错误的更多相关文章
- ASP.NET Web API 路由对象介绍
ASP.NET Web API 路由对象介绍 前言 在ASP.NET.ASP.NET MVC和ASP.NET Web API这些框架中都会发现有路由的身影,它们的原理都差不多,只不过在不同的环境下作了 ...
- 解决asp.net web api时间datetime自动带上带上的T和毫秒的问题
今天用asp.net web api写微信小程序的接口时遇到一个问题. 返回的model中的datetime类型的字段自动转换成了“2014-11-08T01:50:06:234”这样的字符串,带上的 ...
- [翻译]ASP.NET Web API 2 中的全局错误处理
目录 已存在的选项 解决方案预览 设计原则 什么时候去用 方案详情 示例 附录: 基类详情 原文链接 Global Error Handling in ASP.NET Web API 2 由于翻译水平 ...
- ASP.NET Web Api返回对象类型为JSON还是XML
在Umbraco平台上开发过程中,我用WebApi返回JSON result给前端 前端使用React调用这个web api来获取JSON result 我写的web api方法是返回JSON 类型的 ...
- ASP.NET Web API 框架研究 ASP.NET Web API 路由
ASP.NET Web API 核心框架是一个独立的.抽象的消息处理管道,ASP.NET Web API有自己独立的路由系统,是消息处理管道的组成部分,其与ASP.NET路由系统有类似的设计,都能找到 ...
- ASP.NET Web API 2.0 统一响应格式
传统实现 在搭建 Web API 服务的时候,针对客户端请求,我们一般都会自定义响应的 JSON 格式,比如: { "Data" : { "Id" : 100, ...
- ASP.NET Web API WebHost宿主环境中管道、路由
ASP.NET Web API WebHost宿主环境中管道.路由 前言 上篇中说到ASP.NET Web API框架在SelfHost环境中管道.路由的一个形态,本篇就来说明一下在WebHost环境 ...
- ASP.NET Web API Selfhost宿主环境中管道、路由
ASP.NET Web API Selfhost宿主环境中管道.路由 前言 前面的几个篇幅对Web API中的路由和管道进行了简单的介绍并没有详细的去说明一些什么,然而ASP.NET Web API这 ...
- ASP.NET Web API 管道模型
ASP.NET Web API 管道模型 前言 ASP.NET Web API是一个独立的框架,也有着自己的一套消息处理管道,不管是在WebHost宿主环境还是在SelfHost宿主环境请求和响应都是 ...
随机推荐
- 使用注解实现 bean 转 csv
csv 文件是 aaa,bbb,ccc aaa,bbb,ccc 保存 这里的要求是 List<T> 线性表的类型 转换成 类别似 html 中 table的格式,即第一行是 head 后面 ...
- Java集群--大型网站是怎样解决多用户高并发访问的
时间过得真快,再次登录博客园来写博,才发现距离上次的写博时间已经过去了一个月了,虽然是因为自己找了实习,但这也说明自己对时间的掌控能力还是没那么的强,哈哈,看来还需不断的努力啊!(这里得特别说明一下本 ...
- Jndi使用好处,与简单实例【Tomcat】
JNDI学习总结(一)——JNDI数据源的配置 一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动 ...
- WPF界面设计技巧(5)—自定义列表项呈现内容
原文:WPF界面设计技巧(5)-自定义列表项呈现内容 接续上次的程序,稍微改动一下原有样式,并添加一个数据模板,我们就可以达成下面这样的显示功能: 鼠标悬停于文件列表项上,会在工具提示中显示图像缩略图 ...
- C/S与B/S谁与争锋之我见
看到网上有些人在讨论C/S架构和B/S架构以及它们的发展趋势,后起之秀B/S是否真将取代C/S而存在?在发表我的观点之前,我们先来一起来回顾下C/S以及B/S. 一C/S 1.C/S概念 C/S是Cl ...
- Visual Studio跨平台开发实战(3) - Xamarin iOS多页面应用程式开发
原文 Visual Studio跨平台开发实战(3) - Xamarin iOS多页面应用程式开发 前言 在前一篇教学中, 我们学会如何使用Visual Studio 搭配Xcode 进行iOS基本控 ...
- 大页(huge pages) 三大系列 ---计算大页配置参数
使用以下shell 脚本来计算大页配置参数,确保使用脚本实例之前的数据已经开始, 如果数据库的版本号11g,确认是否使用自己主动的内存管理(AMM) +++++++++++++++++++++++++ ...
- Java EE (5) -- Java EE 6 JavaServer Faces Developer Certified Expert(1z0-896)
Section 1: Essentials of JSF2.0 Identify the features of JSF such as Facelets, BookMarkable View, AJ ...
- hdu 2191 悼念512四川汶川大地震遇难者——如今宝,感恩生活
悼念512四川汶川大地震遇难者--如今宝,感恩生活 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Jav ...
- ORACLE 11G没有备份文件參数文件在异机通过rman备份恢复找回被误删的数据
背景: 同事误删除线上数据.所以须要从备份中找回数据恢复. 真实屋漏偏逢连夜雨.船迟又遇打头风.前两天备份的磁盘坏块,如今仅仅有rman全备的.bak文件,没有控制文件和參数文件,所 ...