1

I need to return the full json object (including child json objects), however I'm getting an error... The entity was imported from the database.

error

Self referencing loop detected with type 'System.Data.Entity.DynamicProxies.PhoneNumber_C240BC86FA502D917EFDFC445D42023BBD311F87B9B79339114CAC180EEC83F1'. Path '[0].UserProfile.PhoneNumbers[0].PhoneNumberType.PhoneNumbers'.

Entity

[Table("UserProfile")]
public partial class UserProfile
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public UserProfile()
    {
        PhoneNumbers = new HashSet<PhoneNumber>();
        Users = new HashSet<User>();
        UserEmails = new HashSet<UserEmail>();
    }

    public int Id { get; set; }

    [Column(TypeName = "datetime2")]
    public DateTime? dte_modified { get; set; }

    public string firstname { get; set; }

    public string lastname { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<User> Users { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<UserEmail> UserEmails { get; set; }
}

Api Controller

    [HttpGet]
    [Route("")]
    public IHttpActionResult Get()
    {
        var result = _repository.GetAllUsers();

        return Json(result);
    }

repository

        public IEnumerable<User> GetAllUsers()
    {
        return _context.Users.ToList();
    }
1

2 Answers 2

2

Your issue is caused by one feature of Entity Framework called Lazy Loading, that is enabled by default, and that exception is thrown is because your json serializer is trying to access to each property on an User instance. Property access triggers lazy loading, so more entities get serialized. On those entities properties are accessed, and even more entities are loaded and, as your case, that could end trying to serialize self referencing loops, which is detected by your json serializer.

If you want to load only the scalar properties of User entity, you can disable lazy loading in your context:

public class YourContext : DbContext 
{ 
    public YourContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
        this.Configuration.ProxyCreationEnabled = false; 
    } 
}

If you want to load a related entities as part of your query, you can use Include extension method:

public IEnumerable<User> GetAllUsers()
{
    return _context.Users.Include(u=>u.Users).Include(u=>u.UserEmails).ToList();
}

Another solution is, as was suggested by @DOTang, create a DTO class to project only the data that you need to show in your View.

Update:

Now I found an excellent reference where explain several ways to solve this issue.

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

1 Comment

This did the trick. Thank you! At first, I thought you were messing with me and calling me lazy haha
2

Self-referencing means there is a loop in serilization. It looks like your Phone Numbers has a PhoneNumberType, and the PhoneNumberType has a collection of PhoneNumbers, thus the infinite loop as outlined in the error message. You would be better to convert your collection of objects into a flat ViewModel/Model first that doesn't have any circular dependencies.

So a UserProfileViewModel would have a collection of PhoneNumberViewModels and a PhoneNumberViewModel may have something like this:

public class PhoneNumberViewModel
{
  public string Number {get; set;}
  public string Type {get; set; }
  //other relevant data
}

Where the Type is simply the name of the name, and not the whole object. Feel free to also include any other information the page is showing/info is being used, but you should typically always do this with any sort of ajax call, only return exactly what you need. This removes the circular loop.

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.