23

Give the classes:

public class Parent
{
    public int id {get; set;}
    public int name {get; set;}

    public virtual ICollection<Child> children {get; set;}
}

[Table("Child")]
public partial class Child
{
    [Key]
    public int id {get; set;}
    public string name { get; set; }

    [NotMapped]
    public string nickName { get; set; }
}

And the controller code:

List<Parent> parents = parentRepository.Get();
return Json(parents); 

It works on LOCALHOST, but it does not work on live server:

ERROR : Json A circular reference was detected while serializing an object of type

I did a search and found the [ScriptIgnore] attribute, so I changed the model to

using System.Web.Script.Serialization;

public class Parent
{
    public int id {get; set;}
    public int name {get; set;}

    [ScriptIgnore]
    public virtual ICollection<Child> children {get; set;}
}

But the same error occur on live server (win2008).

How can I avoid that error and serialize the parent data successfully?

RMalke
  • 4,048
  • 29
  • 42
Expert wanna be
  • 10,218
  • 26
  • 105
  • 158
  • 3
    What does `Child` look like? Does it have a back-reference to `Parent`? If so it may make more sense to add `ScriptIgnore` to the back-reference. – D Stanley Jan 29 '13 at 21:41

4 Answers4

48

Try the following code:

return Json(
    parents.Select(x => new {
        id = x.id,
        name = x.name,
        children = x.children.Select(y => new {
            // Assigment of child fields
        })
    })); 

...or if you only need the parent properties:

return Json(
    parents.Select(x => new {
        id = x.id,
        name = x.name
    })); 

It is not really the solution for the problem, but it is a common workaround when serializing DTOs...

RMalke
  • 4,048
  • 29
  • 42
  • Firstly thank you for you comment and how about if I don't need to serialize with children, I need just parent properties then is there any more simple way? – Expert wanna be Jan 29 '13 at 21:56
  • 1
    what if the parent have 100 properties, then do I need to write(select) all the properties? – Expert wanna be Jan 30 '13 at 14:41
  • 1
    @Expertwannabe yeah, you'd need to put'em all... But see, are you sure you're going to need all of it? If it some Service/DTO consumed by some lightweight client, it may be better not to pass all the info. If that's not the case... – RMalke Jan 30 '13 at 15:42
  • I see, thank you very much. I wished there were some except method like 'select all properties except children'. Thanks again! – Expert wanna be Jan 30 '13 at 16:27
  • I have the same issue where it works on localhost but not on the server (iis6, w2003 server). Any ideas on this resolution? – David Aug 06 '13 at 20:16
  • @David I could NOT reproduce the issue and correct the problem. The solution I provided is only a workaround, but it works. – RMalke Aug 06 '13 at 20:23
  • Assuming you're using Entity Framework, taking a look at the entities developed by the framework will shed some light on the topic. For example, I had table called Sessions and one called Enrollments, the Enrollments table having an FK relationship to the Sessions table PK. This resulted in the Session objects having a collection of Enrollments, and the Enrollment objects having a virtual instance of the Session ... which pointed to a collection of Enrollments ... you get the picture, AND why the circular reference issue ... cont'd below – IdahoB May 17 '18 at 15:34
  • Cont'd: The solution was to NOT query a collection of Session objects in the code, but to query an anonymous (untyped) object with all the same fields in it. The prevents the JSON.Encode() from getting confused about, since it doesn't know about, the circular reference that Entity Framework is OK with in the code behind / server side code. – IdahoB May 17 '18 at 15:36
2

I had a similar issue and likewise i was not able to resolve the underlying issue. I figure the server is using a dll different from localhost for the conversion to json via json.encode.

I did post the question and my resolution here A circular reference was detected while serializing with Json.Encode

I resolved with mvchelper.

Community
  • 1
  • 1
David
  • 3,047
  • 4
  • 45
  • 79
1

I'm Using the fix, Because Using Knockout in MVC5 views.

On action

return Json(ModelHelper.GetJsonModel<Core_User>(viewModel));

function

   public static TEntity GetJsonModel<TEntity>(TEntity Entity) where TEntity : class
    {
        TEntity Entity_ = Activator.CreateInstance(typeof(TEntity)) as TEntity;
        foreach (var item in Entity.GetType().GetProperties())
        {
            if (item.PropertyType.ToString().IndexOf("Generic.ICollection") == -1 && item.PropertyType.ToString().IndexOf("SaymenCore.DAL.") == -1)
                item.SetValue(Entity_, Entity.GetPropValue(item.Name));
        }
        return Entity_;  
    }
A.Kosecik
  • 53
  • 3
1

You could use this code and do not use select Extention function to filter your column.

var list = JsonConvert.SerializeObject(Yourmodel,
    Formatting.None,
    new JsonSerializerSettings() {
        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
});
return list;
  • You will get an error if you use this solution and you truly do have a circular reference. Which error? Stackoverflow! (Just tried it and was amused to see the message.) – Thane Plummer Sep 26 '17 at 16:01