Self referencing loop detected - Getting back data from WebApi to the browser
Is this because the Question has Answers and the Answers have a
reference back to Question?
Yes. It cannot be serialized.
EDIT: See Tallmaris's answer and OttO's comment as it is simpler and can be set globally.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Old Answer:
Project the EF object Question
to your own intermediate or DataTransferObject. This Dto can then be serialized successfully.
public class QuestionDto
{
public QuestionDto()
{
this.Answers = new List<Answer>();
}
public int QuestionId { get; set; }
...
...
public string Title { get; set; }
public List<Answer> Answers { get; set; }
}
Something like:
public IList<QuestionDto> GetQuestions(int subTopicId, int questionStatusId)
{
var questions = _questionsRepository.GetAll()
.Where(a => a.SubTopicId == subTopicId &&
(questionStatusId == 99 ||
a.QuestionStatusId == questionStatusId))
.Include(a => a.Answers)
.ToList();
var dto = questions.Select(x => new QuestionDto { Title = x.Title ... } );
return dto;
}
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.ReferenceLoopHandling
= 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
JSON.NET Error Self referencing loop detected for type
The best solution is taken from Loop Reference handling in Web API (which most of this answer is copied from):
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 applyingDataContract
on class, you need to addDataMember
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.
EF WebAPI Self Referencing Loop
I figured this out after some time. The self referencing issue will come up if you are Inheriting from APIController but if you switch to inherit from ODataController everything works.
So
public class MyController : ApiController
{
..... Bunch of code here
}
To
public class MyController : ODataController
{
..... Bunch of code here
}
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
Entity framework self referencing loop detected
Well the correct answer for the default Json formater based on Json.net is to set ReferenceLoopHandling
to Ignore
.
Just add this to the Application_Start
in Global.asax:
HttpConfiguration config = GlobalConfiguration.Configuration;
config.Formatters.JsonFormatter
.SerializerSettings
.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
This is the correct way. It will ignore the reference pointing back to the object.
Other responses focused in changing the list being returned by excluding data or by making a facade object and sometimes that is not an option.
Using the JsonIgnore
attribute to restrict the references can be time consuming and if you want to serialize the tree starting from another point that will be a problem.
Self referencing loop detected while reading data from sql server
_hubcontext.Clients.All.SendAsync("SBSystemBrodcasting", SBSystemApps());
The issue is that you are calling SendAsync
with a Task
. This is not how the API is designed to be used. You should be passing through the actual payload you want to use.
There are multiple ways to solve this. One would be to use:
_hubcontext.Clients.All.SendAsync("SBSystemBrodcasting", SBSystemApps().GetAwaiter().GetResult());
although I would recommend reading this guidance about why it isn't a great idea.
Another would be to change SBSystemApps
so it is synchronous (i.e. returns List<T>
rather than Task<List<T>>
.
Related Topics
Executenonquery for Select SQL Statement Returning No Rows
When a Class Is Inherited from List<>, Xmlserializer Doesn't Serialize Other Attributes
.Net Regex Matching $ with the End of the String and Not of Line, Even with Multiline Enabled
Owin Security - How to Implement Oauth2 Refresh Tokens
How to Remove New Line Characters from a String
+= New Eventhandler(Method) VS += Method
Winforms: Application.Exit VS Environment.Exit VS Form.Close
Using Msbuild to Execute a File System Publish Profile
Calculate the Display Width of a String in C#
Camera.Main Is Null When Performing Raycast
Deferred Execution and Eager Evaluation