ASP.NET Web API序列化JSON错误:“自我引用循环”

与这一次长期斗争。 我正在使用ASP.NET Web API来提供与数据库的简洁HTTP / JSON交互。 我有一个实体名称Reservation with,如下所示:

// Reservation public class Reservation { public int ID { get; set; } // ID (Primary key) public int EquipmentID { get; set; } // EquipmentID public string Username { get; set; } // Username public DateTime BeginDateTime { get; set; } // BeginDateTime public int? Duration { get; set; } // Duration public int? ReservationStateID { get; set; } // ReservationStateID public DateTime? CheckInDateTime { get; set; } // CheckInDateTime public string Note { get; set; } // Note // Foreign keys public virtual Equipment Equipment { get; set; } // FK_Reservation_EquipmentID public virtual ReservationState ReservationState { get; set; } //FK_Reservation_ReservationState } 

到现在为止还挺好。 我正在运行一个简单的python脚本来创建一个新的预留,传递http请求一个Reservation JSON对象。 在以前的生活中,我运行预订添加代码而不进行数据validation,并在HttpActionResult中返回Reservation对象。 我看到的是一个很好的json对象:

{u’Username’:u’name’,u’ReservationStateID’:1,u’Equipment’:None,u’EquipmentID’:2,u’BeginDateTime’:u’2014-05-31T14:00:00Z’, u’Note’:你’,u’CheckInDateTime’:没有,你’Duration’:10800,u’ReservationState’:没有,你”:51}

我有点担心返回的对象中包含的外键设备和ReservationState,这可能会导致更大的问题,但是在适当的时候。 现在,我尝试通过收集预订引用的设备项来运行数据validation

 Equipment equipmentItem = await db.Equipment.FindAsync(newRes.EquipmentID); 

现在,当我尝试执行相同的操作时,在同一个python脚本上使用相同的数据,收到的结果是一个很大的可怕错误:

“’ObjectContent`1’类型无法序列化内容类型’application / json; charset = utf-8’的响应主体。”,u’StackTrace’:无,你’消息’:你发生了错误。 ‘,u’InnerException’:{u’ExceptionMessage’:u“为类型属性’Equipment’检测到自引用循环…

我99%肯定我的数据库中的外键不会创建循环引用,但我在这里唉。 我想再次指出在“成功”的json结果中包含外键。 我敢打赌,如果我能摆脱那些我可以摆脱自我引用的问题。 谢谢您的帮助!

该错误是由EF为外键对象创建代理引起的,当使用代理序列化时,默认的序列化程序(DataContractSerializer)错误。 解决方案是将以下行添加到Global.asax.cs文件中:

 GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

虽然@SKall的答案确实解决了问题,但它并没有在整个项目中解决它,只是对我给出IgnoreDataMember属性的属性。

使用IgnoreDataMember属性标记引用,并告诉我们是否有帮助。

 [IgnoreDataMember] public virtual Equipment Equipment { get; set; } [IgnoreDataMember] public virtual ReservationState ReservationState { get; set; }