S.Koscheyev
S.Koscheyev

Reputation: 13

Web Api returns only one child object from one to many relationship using Entity Framework

I've got a controller method that must return parent object with collection of children. In debug I can see plenty of children during execution but when I catch a json it has only one child.

    [Route("api/page/{id}")]
    public JsonResult GetPage(int id)
    {
        var item = db.Pages.Include(p => p.PageContainerTemplates)
            .SingleOrDefault(p => p.Id == id);
        return Json(item);
    }

I've got many children and Entity Framework Core get them all but response json looks like this:

{
  "name": "Index",
  "bodyClasses": "full-width-container transparent-header",
  "title": "Index",
  "pageContainerTemplates": [
    {
      "position": 8,
      "pageId": 1
    }
  ]
}

Parent object looks like this:

public class Page : BaseEntity
{
    public string Name { get; set; }
    public string BodyClasses { get; set; }
    public string Title { get; set; }
    public virtual List<PageContainerTemplate> PageContainerTemplates { get; set; } 
}

And child looks like this:

public class PageContainerTemplate : BaseEntity
{
    public int Position { get; set; }
    public int PageId { get; set; }
    public Page Page { get; set; }
    public int ContainerTemplateId { get; set; }
    public ContainerTemplate ContainerTemplate { get; set; }
}

I haven't got any additional relationships or any alternative keys but what is strange is than my only child in json haven't got a "containerTemplateId" attribute

Upvotes: 1

Views: 2248

Answers (2)

WernerVA
WernerVA

Reputation: 1091

I had the same issue but the accepted answer here did not work for me.

For me it turned out to be a bug on the child object's equality function.

In my case the child object implements IEquatable<T>. In the implementation of bool Equals(T other) I was comparing the parent ID property and name of the item:

...
public bool Equals(Foo other) {
    if (other == null) return false;

    return ParentId == foo.ParentId && Name == Name;
}

The bug was Name == Name, it should have been Name == other.Name.

Oh how we laughed...

Upvotes: 0

Chris Wallace
Chris Wallace

Reputation: 134

Try this:

services.AddMvc().AddJsonOptions(options => {
            options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });

The issue was discussed https://github.com/aspnet/Mvc/issues/4160 and https://github.com/aspnet/EntityFramework/issues/4646 also see circular reference

Upvotes: 1

Related Questions