"Self Referencing Loop Detected" Exception with JSON.Net

JSON.Net Self referencing loop detected

I just had the same problem with Parent/Child collections and found that post which has solved my case.
I Only wanted to show the List of parent collection items and didn't need any of the child data, therefore i used the following and it worked fine:

JsonConvert.SerializeObject(ResultGroups, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});

JSON.NET Error Self referencing loop detected for type

it also referes to the Json.NET codeplex page at:

http://json.codeplex.com/discussions/272371

Documentation: ReferenceLoopHandling setting

JSON.NET Error Self referencing loop detected for type

That was the best solution
https://learn.microsoft.com/en-us/archive/blogs/hongyes/loop-reference-handling-in-web-api

Fix 1: Ignoring circular reference globally

(I have chosen/tried this one, as have many others)

The json.net serializer has an option to ignore circular references. Put the following code in WebApiConfig.cs file:

 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
= Newtonsoft.Json.ReferenceLoopHandling.Ignore;

The simple fix will make serializer to ignore the reference which will cause a loop. However, it has limitations:

  • The data loses the looping reference information
  • The fix only applies to JSON.net
  • The level of references can't be controlled if there is a deep reference chain

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;

If you want to use this in .Net Core project, you can change Startup.cs as:

  var mvc = services.AddMvc(options =>
{
...
})
.AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);

Fix 2: Preserving circular reference globally

This second fix is similar to the first. Just change the code to:

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
= Newtonsoft.Json.ReferenceLoopHandling.Serialize;
config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
= Newtonsoft.Json.PreserveReferencesHandling.Objects;

The data shape will be changed after applying this setting.

[
{
"$id":"1",
"Category":{
"$id":"2",
"Products":[
{
"$id":"3",
"Category":{
"$ref":"2"
},
"Id":2,
"Name":"Yogurt"
},
{
"$ref":"1"
}
],
"Id":1,
"Name":"Diary"
},
"Id":1,
"Name":"Whole Milk"
},
{
"$ref":"3"
}
]

The $id and $ref keeps the all the references and makes the object graph level flat, but the client code needs to know the shape change to consume the data and it only applies to JSON.NET serializer as well.

Fix 3: Ignore and preserve reference attributes

This fix is decorate attributes on model class to control the serialization behavior on model or property level. To ignore the property:

 public class Category 
{
public int Id { get; set; }
public string Name { get; set; }

[JsonIgnore]
[IgnoreDataMember]
public virtual ICollection<Product> Products { get; set; }
}

JsonIgnore is for JSON.NET and IgnoreDataMember is for XmlDCSerializer.
To preserve reference:

 // Fix 3 
[JsonObject(IsReference = true)]
public class Category
{
public int Id { get; set; }
public string Name { get; set; }

// Fix 3
//[JsonIgnore]
//[IgnoreDataMember]
public virtual ICollection<Product> Products { get; set; }
}

[DataContract(IsReference = true)]
public class Product
{
[Key]
public int Id { get; set; }

[DataMember]
public string Name { get; set; }

[DataMember]
public virtual Category Category { get; set; }
}

JsonObject(IsReference = true)] is for JSON.NET and [DataContract(IsReference = true)] is for XmlDCSerializer. Note that: after applying DataContract on class, you need to add DataMember to properties that you want to serialize.

The attributes can be applied on both json and xml serializer and gives more controls on model class.

ASP.NET. Newtonsoft.Json.JsonSerializationException: 'Self referencing loop detected with type 'E_Store2021.Models.Product'

Not sure if you've solved this already, since it was asked yesterday, or why there were no reactions.

This is a commonly encountered issue when there are circular references in the object structure. The best practice is to avoid these in the first place in your DTOs / viewmodels.

But if it's fine for you to exclude these circular references from the serialization, you're lucky, because you're using Newtonsoft JSON, which supports configuring this behavior via the JsonSerializerSettings.ReferenceLoopHandling option.

I think this should be enough here, since it seems the self-referencing occurs between Products.SubCategory and SubCategory.Products, and what you want is SubCategory.Name, which should still be populated.

If it's not feasible to use this setting, you can just define a ProductDto or ProductViewModel, which could perhaps even flatten the hierarchy, and contain - besides the other properties - a SubCategoryName property instead of including the whole SubCategory entity (or however works for you).

There are three ways to use this aforementioned option.

1) Make it a default setting in ASP.NET Core serialization when you're returning an object result in controller actions:

services.AddMvc()
.AddNewtonsoftJson(options => {
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});

Keep in mind that if you were using ASP.NET Core 3+, and there were no existing AddNewtonsoftJson() call in the configuration beforehand, doing this will replace Microsoft's new System.Text.Json serializer with Newtonsoft's serializer (which is slower).

2) Make it a default global setting for Newtonsoft serializer:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};

// Then all subsequent manual serialization will be done with this setting.
string json = JsonConvert.SerializeObject (object);

Note that configuring it this way won't change the behavior of ASP.NET Core controller actions, because that serialization appears to use a separate settings instance.

3) Pass a JsonSerializerSettings instance each time explicitly when you're manually serializing:

JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
};

string json = JsonConvert.SerializeObject (object, settings);

So, in your case, solution 2) or 3) is what you need. And thanks for the edit; in my original answer I didn't take into consideration that you're manually calling SerializeObject().

Self referencing loop detected in ASP.NET Core

There is no difference in the way self-referencing loops are handled in ASP.NET 4 compared to ASP.NET Core (previously Asp.Net 5). The principles outlined in the question you referenced in your post still apply. However, setting this property in ASP.NET Core is obviously slightly different, given the new method of configuring and bootstrapping the app:

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddJsonOptions(options => {
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
services.AddEntityFramework().AddSqlServer().AddDbContext<IvoryPacketDbContext>(
options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])
);
}

Newtonsoft Json Serialization and Deserialization Issue (Self referencing loop detected for property)

Adding ReferenceLoopHandling.Ignore option Seems to fix the problem.

JsonConvert.SerializeObject(ert, new JsonSerializerSettings{ ReferenceLoopHandling = ReferenceLoopHandling.Ignore})

thanks @Guru Stron

C# Can't serialize my object because of self-referencing loops

You can ignore the self-referencing loops while serializing by using ReferenceLoopHandling.Ignore which will not serialize an object if it is a child object of itself. You can use it by adding it in your serializer settings:

JsonConvert.SerializeObject(Author, Formatting.Indented, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore});

Self referencing loop detected for property in WebApi 2

First of all, change the Navigation properties to virtual, that would provide lazy loading,

public virtual ICollection<Review> Reviews { get; set; }

// In the review, make some changes as well
public virtual Product Product { get; set; }

Secondly, since you know that a Product is not going to always have a review in the collection, can't you set it to nullable? — just saying.

Now back to your question, a pretty much easy way to handle this would be to just ignore the objects which cannot be serialized... Again! Do that using the ReferenceLoopHandling.Ignore setting in the JsonSerializer of Json.NET. For ASP.NET Web API, a global setting can be done (taken from this SO thread),

GlobalConfiguration.Configuration.Formatters
.JsonFormatter.SerializerSettings.Re‌​ferenceLoopHandling
= ReferenceLoopHandling.Ignore;

This error comes from Json.NET when it tried to serialize an object, which had already been serialized (your loop of objects!), and the documentation makes this pretty much clear as well,

Json.NET will ignore objects in reference loops and not serialize them. The first time an object is encountered it will be serialized as usual but if the object is encountered as a child object of itself the serializer will skip serializing it.

Reference captured from, http://www.newtonsoft.com/json/help/html/SerializationSettings.htm



Related Topics



Leave a reply



Submit