13

I am retrieving a JSON object graph via ASP.NET Web API. I'm trying to access the properties from a child entity. When looking at the browser's console, however, it is showing a reference ($ref) to the object, instead of serializing the properties of that object. How do I get access to these properties?

ANGULAR JS VIEW

<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>

SERVICE

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; 
} 

ENDPOINT

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

RATING DOMAIN MODEL

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; }
  }
}

OUTPUT

Please see below URL to see the results I am getting from the API

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Erkan Demir
  • 785
  • 1
  • 8
  • 24
  • 1
    Note: I don't think the AngularJS code or tag add much value here. This is really a question regarding ASP.NET Web API, and will be true independent of what your client code is written in. – Jeremy Caney Jun 11 '15 at 01:10
  • As an aside, do you have a lot invested into your API and client already? If not, you may want to consider making an OData controller instead. OData addresses this issue elegantly by allowing projection to be defined using a consistent Query String parameter. E.g., in this case you'd be able to use `?$expand=RatingDomainModel`. This is a pretty big architectural shift, but if you're early in the project it may provide additional benefits. – Jeremy Caney Jun 11 '15 at 01:13
  • Also, could you post the code from your controller for this particular endpoint? Knowing how you're currently exposing these objects will be useful. – Jeremy Caney Jun 11 '15 at 01:21
  • I have invested a lot into the API. The below code is my service 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(); return result; } – Erkan Demir Jun 11 '15 at 01:37
  • Controller public IHttpActionResult GetRecordsByPageSize(int page) { var companyStatService = new CompanyStatService(); return Ok(companyStatService.GetRecordsByPageSize(page)); } – Erkan Demir Jun 11 '15 at 01:40
  • OK. I've added this code to your question so it's easy for other reviewers to reference. I've also deleted my originally proposed answer because, upon seeing your code, it's clear that you're already using the `Include()` method (or, rather, the related `AllIncluding()` method). – Jeremy Caney Jun 11 '15 at 01:44
  • It's strange, because i can get the company entity field "Company Name" populated but i can not get the Rating Entity field "RatingValue" – Erkan Demir Jun 11 '15 at 01:47
  • 1
    @JeremyCaney: In future, it's probably best to mention that you got the extra code *from comments*, as otherwise it looks to reviewers like you just made it up. – Nathan Tuggy Jun 11 '15 at 01:48
  • @ErkanDemir: Ah, I hadn't paid close enough attention to the output originally; I see what you're talking about now. Can you edit your post to include the `RatingDomainModel` class? Also, what is the data type for the `RatingValue` property? – Jeremy Caney Jun 11 '15 at 01:52
  • @JeremyCaney, just posted it up – Erkan Demir Jun 11 '15 at 01:55
  • @JeremyCaney i got it working. I add the below code into my WebApiConfig.cs config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore; config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None; – Erkan Demir Jun 11 '15 at 02:10
  • @ErkanDemir Aha! Congratulations. For the sake of future viewers, would you mind adding that as an answer? (You can answer your own question). – Jeremy Caney Jun 11 '15 at 02:36
  • @ErkanDemir consider use another layer between the model of the API and the model of how you store the data. – Frankely Diaz Jun 11 '15 at 03:21

1 Answers1

22

Added the below code into WebApiConfig.cs

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =    Newtonsoft.Json.ReferenceLoopHandling.Ignore;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
Erkan Demir
  • 785
  • 1
  • 8
  • 24
  • This helped me out big time! I was almost about to give up and start tearing apart my whole data model. Thanks – Jim K Nov 07 '15 at 22:59