none
Getting JsonSerializationException RRS feed

  • Question

  • Hello,

    I'm having an issue trying to convert an object to json. The error is a Newtonsoft.Json.JsonSerializationException:

    Self referencing loop detected for property 'Project' with type 'System.Data.Entity.DynamicProxies.Project_F29F70EF89942F6344C5B0A3A7910EF55268857CD0ECC4A484776B2F4394EF79'. Path '[0].Categories[0]'.

    The problem is that the object (it's actually a list of objects) has a property which is another object that refers back to the first object:

    public partial class Project
    {
    ...
        public virtual ICollection<Category> Categories { get; set; }
    ...
    }

    public partial class Category
    {
    ...
        public virtual Project Project { get; set; }
    ...
    }

    This is all fine and dandy as far as Entity Framework is concerned, but to convert this to json would result in an infinite regress, hence the exception.

    Here is my code:

            public async Task<HttpResponseMessage> GetProjects()
            {
                var projects = _projectService.GetProjects().ToList();
                string jsonString = JsonConvert.SerializeObject(projects); // <-- Offending line
                return Request.CreateResponse(HttpStatusCode.OK, jsonString);
            }

    I've looked online for solutions to this and I found this stackoverflow post:

    https://stackoverflow.com/questions/7397207/json-net-error-self-referencing-loop-detected-for-type

    They suggest three solutions, none of which work:

    1) Ignore the circular reference:

            public async Task<HttpResponseMessage> GetProjects()
            {
                var projects = _projectService.GetProjects().ToList();
                JsonSerializerSettings settings = new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                string jsonString = JsonConvert.SerializeObject(projects, settings);
                return Request.CreateResponse(HttpStatusCode.OK, jsonString);
            }

    This resulted in the call to SerializeObject(...) hanging for a bit then throwing a  System.OutOfMemoryException (which tells me the circular references were NOT being ignored).

    Mind you, the author of this proposed solution at stackoverflow says to set the ignore setting in WebApiConfig.cs but I tried that and it has no effect.

    He also says:

    "If you want to use this fix in a non-api ASP.NET project, you can add the above line to Global.asax.cs, but first add: var config = GlobalConfiguration.Configuration;"

    Mine's a web API with no global file so I shouldn't have to do this.

    I also don't want to ignore circular references because I don't want to lose data.

    2) Preserve the circular reference:

            public async Task<HttpResponseMessage> GetProjects()
            {
                var projects = _projectService.GetProjects().ToList();
                JsonSerializerSettings settings = new JsonSerializerSettings()
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                    PreserveReferencesHandling = PreserveReferencesHandling.Objects
                };
                string jsonString = JsonConvert.SerializeObject(projects, settings);
                return Request.CreateResponse(HttpStatusCode.OK, jsonString);
            }

    This just resulted in the request timing out because it would just hang.

    Again, the author says to put this in WebApiConfig.cs, but again this had no effect.

    3) Add ignore/preserve reference attributes to the objects and properties:

    Ignoring Categories:

    public partial class Project
    {
    ...
        [JsonIgnore]
        public virtual ICollection<Category> Categories { get; set; }
    ...
    }

    This has no effect. I hover over the project list and see that it still has categories, and each category still has an instance of the project. I still get the same exception.

    Again, even if this worked, I don't want to ignore the categories.

    Preserve Categories:

    [JsonObject(IsReference = true)]
    public partial class Project
    {
    ...
        public virtual ICollection<Category> Categories { get; set; }
    ...
    }

    Again, same results.

    Even if this method worked, the attributes wouldn't be preserved. I'd be doing it on Entity Framework classes which are re-generated automatically every time I recompile. (Is there a way to tell it to set these attributes in the model? Can I set them on the other half of the partial class?)

    Alternatively, I'm open to suggestions other than converting to json and sending back in the response. Is there another way to get the data back to the client?

    What would be the fix to this problem? Thanks.
    • Moved by CoolDadTx Wednesday, January 17, 2018 9:08 PM Third party product
    Wednesday, January 17, 2018 6:34 PM

All replies

  • The error (and questions) you're referring to are coming from Newtonsoft which is a third party products. Please post questions related to third party products in their forums

    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 17, 2018 9:07 PM