ASP.NET Web API:JSON 序列化循环引用

Posted

技术标签:

【中文标题】ASP.NET Web API:JSON 序列化循环引用【英文标题】:ASP.NET Web API: JSON Serializing Circular References 【发布时间】:2015-08-26 12:05:45 【问题描述】:

我正在通过 ASP.NET Web API 检索 JSON 对象图。我正在尝试从子实体访问属性。然而,当查看浏览器的控制台时,它显示的是对象的 reference ($ref),而不是序列化该对象的属性。如何访问这些属性?

角度 JS 视图

<table infinite-scroll='tF.loadMore()' infinite-scroll-disabled='tF.isBusy' infinite-scroll-distance='3' class="responsive">
    <thead>
        <tr>
            <th>FIELD 1</th>
            <th>FIELD 2</th>
            <th>FIELD 3</th>
            <th>FIELD 4</th>
            <th>FIELD 5</th>
        </tr>
    </thead>
    <tbody>
        <tr ng-repeat="item in tF.items | filter:searchFilter">
            <td>item.CompanyDomainModel.CompanyName</td>
            <td>item.RatingDomainModel.RatingValue</td>
            <td>item.Views</td>
            <td>item.Clicks</td>
            <td>item.EmailSent</td>
        </tr>
    </tbody>
    <tfoot ng-show='tF.isBusy'>
        <tr>
            <td colspan="9"><spinner show="tF.isBusy" /><span class="bold">tF.status</span> </td>
        </tr>
    </tfoot>
</table>

服务

public ICollection<CompanyStatDomainModel> GetRecordsByPageSize(int page)  
  const int pgeSize = 20; 
  var result = _companyStatRepo
    .AllIncluding(c => c.CompanyDomainModel, c => c.RatingDomainModel) 
    .OrderBy(c => c.CompanyStatId)
    .Skip(page * pgeSize)
    .Take(pgeSize)
    .ToList(); 
  return result; 
 

端点

IHttpActionResult GetRecordsByPageSize(int page)  
  var companyStatService = new CompanyStatService(); 
  return Ok(companyStatService.GetRecordsByPageSize(page)); 
 

评级域模型

public class RatingDomainModel : IObjectWithState

  [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
  [DataMember]
  public int RatingId  get; set; 

  [DataMember]
  public int CompanyId  get; set; 

  [DataMember]
  public int UserId  get; set; 

  [DataMember]
  public int RatingValue  get; set; 

  [DataMember]
  public DateTime CreatedDate  get; set; 

  //[ForeignKey("UserId")]
  [DataMember]
  public virtual UserDomainModel UserDomainModel  get; set; 

  //[ForeignKey("CompanyId")]
  [DataMember]
  public virtual CompanyDomainModel CompanyDomainModel  get; set; 

  [DataMember]
  public virtual ICollection<CompanyStatDomainModel> CompanyStatDomainModels  get; set; 

  [NotMapped]
  public Common.DataObject.State state  get; set; 

  [NotMapped]
  public bool InDb
  
    get  return this.RatingId != default(int); 
  

  public object PersistenceEntityId
  
    get  return this.RatingId; 
  

输出

【问题讨论】:

注意:我不认为 AngularJS 代码或标签在这里增加了太多价值。这确实是一个关于 ASP.NET Web API 的问题,并且与您的客户端代码编写的内容无关。 顺便说一句,您是否已经在 API 和客户端上投入了大量资金?如果没有,您可能需要考虑制作一个 OData 控制器。 OData 通过允许使用一致的查询字符串参数定义投影来优雅地解决这个问题。例如,在这种情况下,您可以使用 ?$expand=RatingDomainModel。这是一个相当大的架构转变,但如果您处于项目的早期阶段,它可能会带来额外的好处。 另外,你能从你的控制器发布这个特定端点的代码吗?了解您当前如何公开这些对象将很有用。 我在 API 上投入了很多。下面的代码是我的服务 public ICollection GetRecordsByPageSize(int page) const int pgeSize = 20; var result = _companyStatRepo.AllIncluding(c => c.CompanyDomainModel, c => c.RatingDomainModel) .OrderBy(c => c.CompanyStatId).Skip(page * pgeSize).Take(pgeSize).ToList();返回结果; @JeremyCaney:将来,最好提及您获得了 来自 cmets 的额外代码,否则它看起来就像您刚刚编造的一样。跨度> 【参考方案1】:

将以下代码添加到 WebApiConfig.cs 中

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =    Newtonsoft.Json.ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;

【讨论】:

这对我帮助很大!我几乎要放弃并开始撕裂我的整个数据模型。谢谢

以上是关于ASP.NET Web API:JSON 序列化循环引用的主要内容,如果未能解决你的问题,请参考以下文章

反序列化 Json usinc C#, web api, asp.net mvc

在 Asp.Net Web API 中将 JSON 反序列化为派生类型

8 种提升 ASP.NET Web API 性能的方法

8 种提升 ASP.NET Web API 性能的方法

如何在 ASP.NET Web API 中为 Json.NET 设置自定义 JsonSerializerSettings?

如何在我的 ASP.NET Core Web API 中启用 BSON 序列化?