Avoiding Circular Reference for Entity in JSON Serialization

October 17, 2011

Avoiding Circular Reference for Entity in JSON Serialization

One problem that I was facing yesterday while working on an ASP.NET MVC application was a JSON serialization issue. The problem was a circular reference caused by the DataContractJsonSerializer because of relations between the entity and other entities. In this post I’ll show you how you can use a simple workaround in order to avoid the problem.   

The JSON Serialization Error

Returning the output of the JSON method in an ASP.NET MVC controller with a JSON object graph based on an Entity Framework Code First object causes the following error – “A circular reference was detected while serializing an object of type ‘object name’”. Here is an example of a method that might cause the problem:

public ActionResult Details(int id)
    using (var context = new DbEntities())
    {             
        var entity = context.Entities.
          Include(e => e.OtherEntities).
          FirstOrDefault(e => e.EntityId == id);
        return Json(entity, JsonRequestBehavior.AllowGet);
    }
}

Pay attention that this is a fake method and isn’t a real method.

The error I was getting didn’t show up on the server side (nothing crashed). I found the error by inspecting Fiddler since the application kept on working but the client side callback wasn’t. Here is an example of the calling client side function which is using jQuery getJSON function:

function getDetails() {
    $.getJSON('/ApplicationName/Details/' + Id, {}, function (data) {
        fillDetails(data);
    });
}

The circular reference is a known problem that my colleague Ido wrote about in Microsoft Connect.

So how to avoid it?

The Workaround

Use a data projection to project only the relevant data that you need and send this data to the client side. This workaround will minimize the object that you are sending and also play a role as a ViewModel kind of object instead of an entity when it is available on the client side. Here is an example of using the workaround with the previous method:

public ActionResult Details(int id)
{
  using (var context = new DbEntities())
  {
    var entity = context.Entities.
      Include(g => g.OtherEntities).
      Select(e => new { 
        e.Id,
        e.Url,
        e.Name,
        e.OtherEntities
      }).
      FirstOrDefault(e => e.Id == id);
 
    return Json(entity, JsonRequestBehavior.AllowGet);
  }
}

Summary

The circular reference issue might happen also in WCF script services or in other places while serializing Entity Framework’s entities into JSON representation. The simple workaround is to create a projection of the data that you need and serialize it into JSON representation. One of the gains of this method is minimizing the response size from the server.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

one comment

  1. Nuno CostaOctober 17, 2011 ב 12:45

    I belive the same could be achived without projection, just disable LazyLoading an use the Include keyword for related entities

    context.ContextOptions.LazyLoadingEnabled = false;

    var query = from entity in context.Entities.Include(“RelatedEntities”)

               select entity;

    Reply