How to get around the Circular Reference issue with JSON and Entity

I have been experimenting with creating a website that leverages MVC with JSON for my presentation layer and Entity framework for data model/database. My Issue comes into play with serializing my Model objects into JSON.

I am using the code first method to create my database. When doing the code first method a one to many relationship (parent/child) requires the child to have a reference back to the parent. (Example code my be a typo but you get the picture)

class parent
{
   public List<child> Children{get;set;}
   public int Id{get;set;}

}
class child
{
    public int ParentId{get;set;}
    [ForeignKey("ParentId")]
    public parent MyParent{get;set;}
    public string name{get;set;}
 }

When returning a “parent” object via a JsonResult a circular reference error is thrown because “child” has a property of class parent.

I have tried the ScriptIgnore attribute but I lose the ability to look at the child objects. I will need to display information in a parent child view at some point.

I have tried to make base classes for both parent and child that do not have a circular reference. Unfortunately when I attempt to send the baseParent and baseChild these are read by the JSON Parser as their derived classes (I am pretty sure this concept is escaping me).

Base.baseParent basep = (Base.baseParent)parent;
return Json(basep, JsonRequestBehavior.AllowGet);

The one solution I have come up with is to create “View” Models. I create simple versions of the database models that do not include the reference to the parent class. These view models each have method to return the Database Version and a constructor that takes the database model as a parameter (viewmodel.name = databasemodel.name). This method seems forced although it works.

NOTE:I am posting here because I think this is more discussion worthy. I could leverage a different design pattern to over come this issue or it could be as simple as using a different attribute on my model. In my searching I have not seen a good method to overcome this problem.

My end goal would be to have a nice MVC application that heavily leverages JSON for communicating with the server and displaying data. While maintaining a consistant model across layers (or as best as I can come up with).

I see two distinct subjects in your question:

  • How to manage circular references when serializing to JSON?
  • How safe is it to use EF entities as model entities in you views?

Concerning circular references I’m sorry to say that there is no simple solution. First because JSON cannot be used to represent circular references, the following code:

var aParent = {Children : []}, aChild  = {Parent : aParent};
aParent.Children.push(aChild);
JSON.stringify(aParent);

Results in: TypeError: Converting circular structure to JSON

The only choice you have is to keep only the composite –> component part of the composition and discard the “back navigation” component –> composite, thus in you example:

class parent
{
    public List<child> Children{get;set;}
    public int Id{get;set;}
}
class child
{
    public int ParentId{get;set;}
    [ForeignKey("ParentId"), ScriptIgnore]
    public parent MyParent{get;set;}
    public string name{get;set;}
}

Nothing prevents you from recomposing this navigation property on your client side, here using jQuery:

$.each(parent.Children, function(i, child) {
  child.Parent = parent;  
})

But then you will need to discard it again before sending it back to the server, for JSON.stringify won’t be able to serialize the circular reference:

$.each(parent.Children, function(i, child) {
  delete child.Parent;  
})

Now there is the issue of using EF entities as your view model entities.

First EF is likely to using Dynamic Proxies of your class to implement behaviors such as change detection or lazy loading, you have to disable those if you want to serialize the EF entities.

Moreover using EF entities in the UI can be at risk since all the default binder will mapping every field from the request to entities fields including those you did not want the user to set.

Thus, if you want you MVC app to be properly designed I would recommended to use a dedicated view model to prevent the “guts” of your internal business model from being exposed to the client, thus I would recommend you a specific view model.

3

A simpler alternative to attempting to serialize the objects would be to disable the serialization of parent/child objects. Instead, you could make a separate call to fetch the associated parent/child objects as and when you need them. This may not be ideal for your application, but it’s an option.

To do this, you could set up a DataContractSerializer and set the DataContractSerializer.PreserveObjectReferences property to ‘false’ in the constructor of your data model class. This specifies that the object references should not be preserved on serializing the HTTP responses.

Examples:

Json format:

var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = 
    Newtonsoft.Json.PreserveReferencesHandling.None;

XML format:

var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
var dcs = new DataContractSerializer(typeof(Employee), null, int.MaxValue, 
    false, /* preserveObjectReferences: */ false, null);
xml.SetSerializer<Employee>(dcs);

This means that if you fetch an item which has child objects referenced, the child objects won’t be serialized.

See also the DataContractsSerializer class.

JSON serializer that deals with Circular References

Here is an example custom Jackson JSONSerializer that deals with circular references by serializing the first occurrence and storing a *reference to the first occurrence on all subsequent occurrences.

Dealing with Circular References when Serializing objects with Jackson

Relevant partial snippet from the above article:

private final Set<ObjectName> seen;

/**
 * Serialize an ObjectName with all its attributes or only its String representation if it is a circular reference.
 * @param on ObjectName to serialize
 * @param jgen JsonGenerator to build the output
 * @param provider SerializerProvider
 * @throws IOException
 * @throws JsonProcessingException
 */
@Override
public void serialize(@Nonnull final ObjectName on, @Nonnull final JsonGenerator jgen, @Nonnull final SerializerProvider provider) throws IOException, JsonProcessingException
{
    if (this.seen.contains(on))
    {
        jgen.writeString(on.toString());
    }
    else
    {
        this.seen.add(on);
        jgen.writeStartObject();
        final List<MBeanAttributeInfo> ais = this.getAttributeInfos(on);
        for (final MBeanAttributeInfo ai : ais)
        {
            final Object attribute = this.getAttribute(on, ai.getName());
            jgen.writeObjectField(ai.getName(), attribute);
        }
        jgen.writeEndObject();
    }
}

The one solution I have come up with is to create “View” Models. I
create simple versions of the database models that do not include the
reference to the parent class. These view models each have method to
return the Database Version and a constructor that takes the database
model as a parameter (viewmodel.name = databasemodel.name). This
method seems forced although it works.

Sending out the bare minimum of data is the only correct answer. When you send out data from the database, it usually doesn’t make sense to send out every single column with all the associations. The consumers shouldn’t need to deal with database associations and structures, that is for databases. Not only will this save bandwidth but it’s also much easier to maintain, read and consume. Query the data and then model it for what you actually need to send out eq. the bare minimum.

2

.Include(x => x.TableName ) not returning relationships (from principal table to dependent table), or only returning one row of data, FIX HERE:

https://stackoverflow.com/questions/43127957/include-not-working-in-net-core-returns-one-parent

Also, in Startup.cs make sure you have this at the top:

using Microsoft.EntityFrameworkCore; 
using Newtonsoft.Json; 
using Project_Name_Here.Models;

1

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật