Skip to content

Instantly share code, notes, and snippets.

@lnickers2004
Last active January 3, 2016 13:09
Show Gist options
  • Save lnickers2004/8467962 to your computer and use it in GitHub Desktop.
Save lnickers2004/8467962 to your computer and use it in GitHub Desktop.
WebApi 2: JSON Serialization Exception-- self-referencing circular reference exception Solution 1: project anonymous types removing the self-referring offending property Solution 2: Use a projection into a DTO Model that does not have the self referencing property Solution 3: Use a projection into a Model Factory to create our DTO with flexibili…
using CountingKs.Data;
using CountingKs.Data.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace CountingKs.Controllers
{
public class FoodsController : ApiController
{
private ICountingKsRepository _repo;
public FoodsController(ICountingKsRepository repo)
{
_repo = repo;
}
public IEnumerable<object> Get()
{
//The following code causes exception
//
//message: "An error has occurred."
//exceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
//exceptionType: "System.InvalidOperationException"
//stackTrace: null
//innerException: {
//message: "An error has occurred."
//exceptionMessage: "Self referencing loop detected for property 'food' with type 'CountingKs.Data.Entities.Food'. Path '[0].measures[0]'."
//exceptionType: "Newtonsoft.Json.JsonSerializationException"
//
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList();
//There are a few ways to fix this
//Method 1: project the childe object without a reference back to the parent of the relation
var results = _repo.GetAllFoodsWithMeasures()
.OrderBy(f => f.Description)
.Take(25)
.ToList().Select(f => new{
Description = f.Description,
Measures = f.Measures.Select(m =>
new
{
Description = m.Description,
Calories = m.Calories
})
});
return results;
}
}
}
using CountingKs.Data;
using CountingKs.Data.Entities;
using CountingKs.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace CountingKs.Controllers
{
public class FoodsController : ApiController
{
private ICountingKsRepository _repo;
public FoodsController(ICountingKsRepository repo)
{
_repo = repo;
}
public IEnumerable<FoodModel> Get()
{
//The following code causes exception
//
//message: "An error has occurred."
//exceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
//exceptionType: "System.InvalidOperationException"
//stackTrace: null
//innerException: {
//message: "An error has occurred."
//exceptionMessage: "Self referencing loop detected for property 'food' with type 'CountingKs.Data.Entities.Food'. Path '[0].measures[0]'."
//exceptionType: "Newtonsoft.Json.JsonSerializationException"
//
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList();
//There are a few ways to fix this
//Method 1: project the childe object without a reference back to the parent of the relation
//this is a fragile...
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList().Select(f => new{
// Description = f.Description,
// Measures = f.Measures.Select(m =>
// new
// {
// Description = m.Description,
// Calories = m.Calories
// })
// });
// return results;
//Method 2 add a DTO, ViewModel that holds only what you wish to serialize to clients
//(Automapper can help here-- See http://lostechies.com/jimmybogard/2013/08/25/automapper-3-0-released/
var results = _repo.GetAllFoodsWithMeasures()
.OrderBy(f => f.Description)
.Take(25)
.ToList().Select(f => new FoodModel
{
Description = f.Description,
Measures = f.Measures.Select(m =>
new MeasureModel
{
Description = m.Description,
Calories = m.Calories
})
});
return results;
}
}
}
using CountingKs.Data;
using CountingKs.Data.Entities;
using CountingKs.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
namespace CountingKs.Controllers
{
public class FoodsController : ApiController
{
private ICountingKsRepository _repo;
private ModelFactory _modelFactory;
public FoodsController(ICountingKsRepository repo)
{
_repo = repo;
_modelFactory = new ModelFactory();//we intentionally did not use dependency injection
}
public IEnumerable<FoodModel> Get()
{
//The following code causes exception
//
//message: "An error has occurred."
//exceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
//exceptionType: "System.InvalidOperationException"
//stackTrace: null
//innerException: {
//message: "An error has occurred."
//exceptionMessage: "Self referencing loop detected for property 'food' with type 'CountingKs.Data.Entities.Food'. Path '[0].measures[0]'."
//exceptionType: "Newtonsoft.Json.JsonSerializationException"
//
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList();
//There are a few ways to fix this
//Method 1: project the childe object without a reference back to the parent of the relation
//this is a fragile...
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList().Select(f => new{
// Description = f.Description,
// Measures = f.Measures.Select(m =>
// new
// {
// Description = m.Description,
// Calories = m.Calories
// })
// });
// return results;
//Method 2 add a DTO, ViewModel that holds only what you wish to serialize to clients
//(Automapper can help here-- See http://lostechies.com/jimmybogard/2013/08/25/automapper-3-0-released/
//var results = _repo.GetAllFoodsWithMeasures()
// .OrderBy(f => f.Description)
// .Take(25)
// .ToList().Select(f => new FoodModel
// {
// Description = f.Description,
// Measures = f.Measures.Select(m =>
// new MeasureModel
// {
// Description = m.Description,
// Calories = m.Calories
// })
// });
// return results;
//Method 3: Use a Factory Pattern to return our DTO view models
//NOTE: WE CHOOSE NOT to use Automapper, because we want to be able to build return URI's etc into
//to return data e.g. HATEOS Hypermedia etc
//using a Model Factory, we have only one place to handling Mapping from
//Database entities to DTO's
var results = _repo.GetAllFoodsWithMeasures()
.OrderBy(f => f.Description)
.Take(25)
.ToList().Select(f => _modelFactory.Create(f));
return results;
}
}
}
{
message: "An error has occurred."
exceptionMessage: "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'."
exceptionType: "System.InvalidOperationException"
stackTrace: null
innerException: {
message: "An error has occurred."
exceptionMessage: "Self referencing loop detected for property 'food' with type 'CountingKs.Data.Entities.Food'. Path '[0].measures[0]'."
exceptionType: "Newtonsoft.Json.JsonSerializationException"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment