-2

Consider a database with Order and OrderLines tables and one-to-many relationship between them (this is for MCVE; the actual context is more complex). If I scaffold the model, I get the following:

public partial class Order {
    public virtual ICollection<OrderLines> OrderLines {get; set;}
}

and

public partial class OrderLines {
    public virtual int OrderId {get; set;}
    public virtual Order Order {get; set;}
}

Now, if I generate OrdersController, the GET method is also quite straightforward:

[HttpGet]
public ActionResult<IEnumerable<Order>> Order() {
    return _context.Order.ToList();
}

And I get a nice JSON string in return. However, if I add Include() to the get method like this:

    return _context.Order.Include(o => o.OrderLines).ToList();

the resulting string is cut in the middle. When I debug, it seems that the program gets into infinite loop from OrderLines to Order and then back to OrderLines. If I remove Order variable from OrderLines and only leave OrderId, everything works fine (which supports my hypothesis about infinite loop).

Obviously, it is somewhat primitive example; I should be using ViewModel - but still, shouldn't the code above be valid? I haven't used Include() for years, but I am pretty sure that in earlier versions of EF it was working fine.

What is the recommended way to get the object and its child collection?

Felix
  • 9,248
  • 10
  • 57
  • 89
  • **Never** return Entity Framework queries, always materialize first – Camilo Terevinto Nov 24 '18 at 19:04
  • sorry - I missed `ToList()` during cut and paste. Updated – Felix Nov 24 '18 at 19:12
  • 1
    @CamiloTerevinto - I was googling using all kind of keywords, and the question that you referenced never came up. Also, for some reason I didn't get any error. So, while I agree that that question provides correct answer, I would suggest to keep my question open... :) – Felix Nov 24 '18 at 19:21
  • 1
    regarding the duplicate question, the answer is present in several other questions, however, the question is from a different perspective. Many are stuck at this stage and I don't see people with this issue having finding that solution – Neville Nazerane Nov 24 '18 at 19:22
  • The problem is still the same, regardless of it not looking like that. The error seems to be silently ignored for some reason (unless you are not actually looking at the logs...). There, I added a better duplicate – Camilo Terevinto Nov 24 '18 at 19:29
  • 1
    True the problem is the same. The above question is the common scenario where you face the problem. The scenario cannot really be linked to the problem. It took me a while the first time too. Makes sense to have a question in this format so as to help others find its solution sooner – Neville Nazerane Nov 24 '18 at 19:34

1 Answers1

1

Your output object has a circular reference that doesn't get serialized by default.

In your startup class, find the line services.AddMvc() and update it as follows:

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

Check this link for more information.

Neville Nazerane
  • 6,622
  • 3
  • 46
  • 79
  • Ouch! I was reading that page but just through Eager and Explicit loading (and Explicit Loading actually works as well); but ignored Lazy loading since it didn't apply to me... Thank you – Felix Nov 24 '18 at 19:23
  • I would not ask you to use lazy loading. I don't think that applies to real-world application. It's just a shortcut. I provided the link since it contains the same code at the bottom of the page – Neville Nazerane Nov 24 '18 at 19:24
  • 1
    Understood... I am saying that I stopped at lazy loading and missed the explanation below it. The good thing is that I got a perfect answer that eluded me for a day; although it cost me two downvotes... Oh well – Felix Nov 24 '18 at 19:26