Monday, April 11, 2011

Entity framework and JSON - A circular reference was detected while serializing an object

I have an MVC application in which I am calling a controller method
from JavaScript and return the result to JavaScript callback in JSON
format.

I got this error when trying to serialise an entity object into JSON

"A circular reference was detected while serializing an object [...]"

I took me about half an hour to find out what was causing the error by
using my trusted reference book Google. If you want to jump ahead to
the solution, please feel free to do so. It's clearly marked at the
end of this article. The error was caused by the entity object having
a reference to a related object. In my case it was subcategory to
category. For some reason, that I have not looked into yet, JSON
serialisation has an issue when trying to deal with these related
entities.

Now one of the solutions is to remove the related entity by not using
the "include" method when retrieving the object and hence losing the
relationship between subcategory and category in the controller and
subsequently in the view. This was not an option for me as I needed
the relationship.

Finally after another hour trying to find different solutions to this
problem, I managed to get the following code to work.

            var results = from x in MyEntityObject()
                          select new
                          {
                              Id = x.Id,
                              Name = x.Name,
                              Description = x.Description,
                              CategoryId = x.TreatmentType.Id,
                              CategoryName = x.TreatmentType.Name
                          };
      
            return Json(results);

The trick is to take the related objects and create a new JSON results
object which is then returned by the controller to the JavaScript
callback function.


$.post("/Category/EditSubCategory/" + id,
            { "name": name, "description": description, "categoryId": categoryid },
            (function (result) {
                //bind the properties
                $.each(result, function () {
                    if (this.Id == id) {
                        $('#tmtsrvtxt_name_' + id).html(this.Name);
                        $('#tmtsrvitem_name_' + id).val(this.Name);
                        $('#tmtsrvtxt_desc_' + id).html(this.Description);
                        $('#tmtsrvitem_desc_' + id).val(this.Description);
                        $('#tmtsrvtxt_ctgr_' + id).html(this.CategoryName);
                        $('#tmtsrvitem_ctgr_' + id).val(this.CategoryId);
                    }
                });
            }),
            "json");
Hope this saves you a couple of hours and helps you along the way.