Self referencing loop detected - Getting back data from WebApi to the browser
Solution 1
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;
}
Solution 2
You can also try this in your Application_Start()
:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Serialize;
It should fix your problem without going through many hoops.
EDIT: As per OttO's comment below, use:
ReferenceLoopHandling.Ignore
instead.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
Solution 3
In ASP.NET Core the fix is as follows:
services
.AddMvc()
.AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
Solution 4
If using OWIN, remember, no more GlobalSettings for you! You must modify this same setting in an HttpConfiguration object which gets passed to the IAppBuilder UseWebApi function (or whatever service platform you're on)
Would look something like this.
public void Configuration(IAppBuilder app)
{
//auth config, service registration, etc
var config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
//other config settings, dependency injection/resolver settings, etc
app.UseWebApi(config);
}
Solution 5
ASP.NET Core Web-API (.NET Core 2.0):
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.Configure<MvcJsonOptions>(config =>
{
config.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
}
Related videos on Youtube
Admin
Updated on March 19, 2022Comments
-
Admin about 2 years
I am using Entity Framework and having a problem with getting parent and child data to the browser. Here are my classes:
public class Question { public int QuestionId { get; set; } public string Title { get; set; } public virtual ICollection<Answer> Answers { get; set; } } public class Answer { public int AnswerId { get; set; } public string Text { get; set; } public int QuestionId { get; set; } public virtual Question Question { get; set; } }
I am using the following code to return the question and answer data:
public IList<Question> GetQuestions(int subTopicId, int questionStatusId) { var questions = _questionsRepository.GetAll() .Where(a => a.SubTopicId == subTopicId && (questionStatusId == 99 || a.QuestionStatusId == questionStatusId)) .Include(a => a.Answers) .ToList(); return questions; }
On the C# side this seems to work however I notice that the answer objects have references back to the question. When I use the WebAPI to get the data to the browser I get the following message:
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.
Self referencing loop detected for property 'question' with type 'Models.Core.Question'.
Is this because the Question has Answers and the Answers have a reference back to Question? All the places I have looked suggest having a reference to the parent in the child so I am not sure what to do. Can someone give me some advice on this.
-
cuongle almost 11 yearsUse Dto for your web api, avoiding return Entity directly in your reaponse
-
Admin almost 11 yearsWhat is Dto? Our whole application uses EF, we are using AngularJS on the client, and we have no problems other than for this one case.
-
cuongle almost 11 yearsWhat I meant you should define your Dto for your Web Api, Dto is kind of similar with ViewModel in MVC. Dto is like a wrapper o your EF model to provide data your your client (angularjs).
-
mayabelle over 10 yearspossible duplicate of JSON.NET Error Self referencing loop detected for type
-
Murat Yıldız almost 6 yearsYou might have a look at my answer on “Self Referencing Loop Detected” exception with JSON.Net page.
-
-
OttO over 10 yearsI know this is an old thread but for those who stumble upon it in the future, try: GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
-
J86 almost 10 years@OttO, your suggestions worked for me. Thanks very much.
-
Claiton Lovato over 8 yearsI would like to add, for me setting ReferenceLoopHandling.Ignore did not work, setting it globaly or on the API startup didnt work at all. I managed to get it working by decorating the navigation property of the child class with [JsonIgnore] . I still get the ParentId but the Parent navigation is ignored while serialising.
-
Michał W. over 8 yearsIn asp-net rc-1-final i believe it is "services.Configure<MvcOptions>" now
-
Admin almost 8 yearsJsonOutputFormatter is in the namespace Microsoft.AspNet.Mvc.Formatters
-
Microsoft Developer almost 8 yearsCode goes into infinite loop and shows stack overflow exception after adding this line.
-
aherrick almost 8 yearsFor .NET Core 1.0 RTM: new JsonOutputFormatter(serializerSettings, ArrayPool<char>.Shared);
-
Dragos Durlut over 7 yearsGlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; works better
-
Sithu over 7 yearsYou saved my day. I was wondering why the answer above was not working. Yes, using OWIN setting in Global.asax will not work.
-
Tallmaris over 7 years@Demodave you have to create your JsonSerializer using the static
Create()
method that accepts a setting as parameter. Docs: newtonsoft.com/json/help/html/… -
Bartosz almost 7 yearsHello, Ignoring the serialization will break the circular dependency Question>Answer>Question. Does the DTO approach preserve it?
-
Ren over 5 yearsI have this problem in an old ASP.NET MVC project. GlobalConfiguration.Configuration does not have Formatters. Can you plz suggest what can be done for that?
-
anhtv13 almost 4 yearsGlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; -> Where to put this line of code???
-
Christopher over 2 yearsThis is what I needed - thank you!