原文地址:http://www.it165.net/pro/html/201210/3932.html

最近开始研究Web API,运气不错第一个测试项目就遇到问题@@-当新增Control时选择[API Controller woth read/write actions, using Entity Framework]然后使用Northwnd数据库,数据表选择Orders,Order_Details,Products.

前端javascript程序代码如下

01.@section scripts{
02.<script type="text/javascript">
03.$(document).ready(function () {
04. 
05.$.getJSON('/api/order/', function (data) {
06.alert(data);
07.})
08..error(function (jqXHR, textStatus, err) {
09.alert('Error: ' + err);
10.});
11.});
12.</script>
13.}

执行后出现错误,查询完整的错误说明为Self referencing loop detected…,也就是循环参考.

这错误讯息好熟悉,突然想起以前开发Silverlight RIA Service好像也有类似情况.经上网查询原因后果不其然,问题是一样的,因为ASP.Net
MVC Web
API预设采用JSON.Net作为输出转换,而预设的情况下JSON.Net会自动一层层解析要输出的对象之属性,也就说这个例子中的输出对象为
Order,其中有个属性为Order_Details,而Order_Details也有个属性参考至Order,所以产生了循环相依问题,导致错误产
生.

这个问题处理方式有三种 www.it165.net

1.最简单的方式就是从Entity
Framework着手,停用LazyLoading与ProxyCreation.因为LazyLoading停用后那么当JSON.Net解析
Order对象时其属性Order_Details会返回null(不会自动加载).所以也就避免了此问题

当然此方式的缺点会导致后续程序存取Entity Object时牺牲了LazyLoading的方便性,需要手动处理此问题.

1.db.Configuration.LazyLoadingEnabled = false;
2.db.Configuration.ProxyCreationEnabled = false;
3. 
4.return db.Orders.AsEnumerable();

2.设定JSON.Net忽略循环参考

透过APP_Start的WebApiConfig.cs,设定
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
= Newtonsoft.Json.ReferenceLoopHandling.Ignore;

使用这个方式时要注意,它只是忽略循环参考的错误,但实际上还是会自动一层层解析要输出的对象之属性,所以若数据会相依有可能会产生无穷循环.

3.设定JSON.Net避免循环参考

透过APP_Start的WebApiConfig.cs,设定

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;

config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
= Newtonsoft.Json.PreserveReferencesHandling.Objects;

这种做法与2的差异在于它会将重复过的对象用一个代表取代,譬如底下JSON格式
1:
[{"$id":"1","Category":{"$id":"2","Products":[{"$id":"3","Category":{"$ref":"2"},"Id":2,"Name":"Yogurt"},{"$ref":"1"}],"Id":1,"Name":"Diary"},"Id":1,"Name":"Whole
Milk"},{"$ref":"3"}]

所以对于数据而言这种作法还是会自动一层层解析要输出的对象之属性,只是避免输出太大量数据.

4.手动设定避免循环参考

如同3的模式,透过[JsonIgnore] 与[JsonObject(IsReference = true)] 细部设定,可以更精确的设定每个要输出的属性.

缺点是1.设定繁杂. 2.只能通用设定无法例外. 3.因为必须直接或透过 partial class方式设定,故无法将设定与Entity Object class做分离

以上作法实际上都有其优缺点, 并没有一个可以通用的模式, 须看需求而定,这问题与同早期RIA Service的问题相同,但这边提供一种比较通用的模式就是采用方法1+方法2或3.

停用LazyLoading,而使用程序的方式(透过 Include方法)决定那些属性要输出.

ASP.Net MVC-Web API使用Entity Framework时遇到Loop Reference的更多相关文章

  1. [译]ABP框架使用AngularJs,ASP.NET MVC,Web API和EntityFramework构建N层架构的SPA应用程序

    本文转自:http://www.skcode.cn/archives/281 本文演示ABP框架如何使用AngularJs,ASP.NET MVC,Web API 和EntityFramework构建 ...

  2. ABP 教程文档 1-1 手把手引进门之 AngularJs, ASP.NET MVC, Web API 和 EntityFramework(官方教程翻译版 版本3.2.5)含学习资料

    本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 转载请注明出处:http://www.cnblogs.com/yabu007/  谢谢 官方文档分四部分 一. 教程文档 二.ABP 框架 三. ...

  3. Asp.net mvc web api 在项目中的实际应用

    Asp.net mvc web api 在项目中的实际应用 前言:以下只是记录本人在项目中的应用,而web api在数据传输方面有多种实现方式,具体可根据实际情况而定! 1:数据传输前的加密,以下用到 ...

  4. ASP.NET MVC Web API 学习笔记---第一个Web API程序

    http://www.cnblogs.com/qingyuan/archive/2012/10/12/2720824.html GetListAll /api/Contact GetListBySex ...

  5. ASP.NET MVC Web API Post FromBody(Web API 如何正确 Post)

    问题场景: ASP.NET MVC Web API 定义 Post 方法,HttpClient 使用 JsonConvert.SerializeObject 传参进行调用,比如 Web Api 中定义 ...

  6. ASP.NET MVC Web API For APP

    近来很多大型的平台都公开了Web API.比如百度地图 Web API,做过地图相关的人都熟悉.公开服务这种方式可以使它易于与各种各样的设备和客户端平台集成功能,以及通过在浏览器中使用 JavaScr ...

  7. 【转载】ASP.NET MVC Web API 学习笔记---联系人增删改查

    本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查.目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的.下面我们通过创建一个简单的Web API来管理联系 ...

  8. 实战 ASP.NET MVC Web API

    实战 ASP.NET MVC Web API Web API 框架基于 ASP.NET MVC 框架开发,是一个面向 Http 协议的通信框架.相对于 WCF 而言,Web API 只面向于 Http ...

  9. ASP.NET MVC Web API 学习笔记---联系人增删改查

    本章节简单介绍一下使用ASP.NET MVC Web API 做增删改查. 目前很多Http服务还是通过REST或者类似RESP的模型来进行数据操作的. 下面我们通过创建一个简单的Web API来管理 ...

随机推荐

  1. PHP面向对象的基本写法(区别于java)

    <?php /** * 这是一个人的对象 */ class ClassName { public $name; public $age; public $sex; public static $ ...

  2. 自定义Window 服务

    自定义window 服务 开发到使用的流程: 1.完成对应的代码之后(代码在底下),右键MyService.cs 添加安装程序 2.添加window服务安装程序打开Service1.cs[设计]页面, ...

  3. 设置 textField.placeholder的颜色和大小

    textField.placeholder = @"请输入手机号码"; [textField setValue:[UIColor blue] forKeyPath:@"_ ...

  4. base64加密解密文件

    1 //字符串加密 -(void)demo1 { //普通的 8 bit二进制数据 NSString *str = @"hello world!"; //将字符串转换成二进制数据 ...

  5. window对象细节(转载)

    Window对象是客户端javascript最高层对象之一,只要打开浏览器窗口,不管该窗口中是否有打开的网页,当遇到BODY.FRAMESET或FRAME元素时,都会自动建立window对象的实例.另 ...

  6. c++ string用法

    首先,为了在我们的程序中使用string类型,我们必须包含头文件 .如下: #include  //注意这里不是string.h string.h是C字符串头文件 1.声明一个C++字符串 声明一个字 ...

  7. 移动Web开发,4行代码检测浏览器是否支持position:fixed

    不废话,直接上代码 var div = document.createElement('div'); div.style.cssText = 'display:none;position:fixed; ...

  8. python运维开发之路第一天

    一.python安装及环境变量配置 1.windows7安装python 1)下载地址:https://www.python.org/downloads/windows/ 如下图: 注意:下载,用代理 ...

  9. 使用Python操作Redis

    1. 安装pyredis 首先安装pip   1 2 3 4 5 6 7 8 <SHELL># apt-get install python-pip ...... <SHELL> ...

  10. eclipse 比较好的插件

    tomcat 插件 egit github 插件 subeclipse 插件 Properties Editor Properties Editor 编辑java的属性文件,并可以自动存盘为Unico ...