4

I'm trying to serialize a complex object with virtual navigation properties. For some reason, when I try to serialize this object using WebApi (returning it from a controller) or with JsonConvert.Serialize(myObject) all of my virtual properties are null. When I inspect my object, I can see that all of these are proxy objects. For some reason json.net is not playing nice with these proxy objects. How do I get virtual properties to serialize?

3
  • 1
    Sounds like these objects are lazy-loaded EF entities, yes? Commented Apr 16, 2013 at 20:26
  • Exactly. Any thoughts? Commented Apr 16, 2013 at 20:30
  • 1
    Only that IMHO, you shouldn't be sending EF entities out for serialization. It is usually a good idea to create another flat object that you can copy the data to before serializing. Otherwise, where is the serializer supposed to stop? It would end up serializing the entire model. Is this what you want? Commented Apr 16, 2013 at 20:32

1 Answer 1

4

The problem, as mentioned in the comments, is that trying to serialize Entity Framework properties which are lazy loaded doesn't work like that. If all proxy links were chained, you could end up serializing your entire database with a simple call.

So when serializing, anything which has not been explicitly loaded is given a null value. Whenever you try and load a proxy object, a database call is made (once per object).

You can get around this is a number of different ways. Imagine you have the following entity objects:

public class Person
{
    public int ID
    public string PersonName
    public Address PersonAddress
}

public class Address
{
    public int ID
    public string AddressLine
}

Assuming you load your entities like so:

Person myPerson = ObjectContext.CreateObjectSet<Person>.Where(p => p.ID == 1);

You could do (not really recommended, as it would create two separate database calls):

Person myPerson = ObjectContext.CreateObjectSet<Person>.Where(p => p.ID == 1);
var x = myPerson.Address;

A better way would be to do:

Person myPerson = ObjectContext.CreateObjectSet<Person>
.Include("PersonAddress")
.Where(p => p.ID == 1);

This would avoid your related objects being lazy loaded entirely.

Enormous caveat

If you try and perform any nested eager loading (say you had an AddressCountry object, and you wanted to eager load by changing your include to be .Include("PersonAddress.AddressCountry")), there are severe performance problems that can arise, especially if you have large datasets.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.