Handling Circular References ASP.NET MVC Json Serialization

I love the Entity Framework CodeFirst stuff, combined with scaffolding, it makes development go so fast. Fast that is until you drop an API into the mix and want that to serve Json.

Here’s my EF Model. Lots of lovely navigation properties allowing me to get from any entity to any other one. Handy-dandy in .NET land…

models

But no-bueno when serializing using the out of the box Json serializer…

[HttpGet]
public JsonResult Get(int id)
{
    return Json(itemcategoryRepository.Find(id),
        JsonRequestBehavior.AllowGet);
}

Now, this sucks because how awesomely elegant is that code? What you get is an error like this:

A circular reference was detected while serializing an object of type ‘System.Data.Entity.DynamicProxies.ItemCategory_A79…’.

Json Serialization Options

There are a few ways to go here – you could use ViewModels everywhere and sloppy-copy properties across as needed. Even with Automapper to take the drugery out of this, it rubs me the wrong way – what’s the point of using EF if I still have to have a separate set of Poco ViewModels?

Another option is to add a .ToJson method to the EF classes, and emit strings. Lots of control, but… meh.

Using Json.net comes up a lot, but it’s also labor intensive.

What I ended up doing is using Linq to project the EF object graph into an anonymous object graph. Here’s an example that serializes two levels of objects (a list of ItemCategories, each of which can contain a list of Items – see the object model above)

[HttpGet]
public JsonResult List()
{
    var data = itemcategoryRepository
        .AllIncluding(itemcategory => itemcategory.Items);
    //Project into anonymous objects because Serializers
    //can't handle circular refs in the EF magic
    var collection = data.Select(x => new
    {
        id = x.Id,
        name = x.Name,
        items = x.Items.Select(item => new
        {
            id=item.Id,
            name = item.Name
        })
    });
    return Json(collection,
        JsonRequestBehavior.AllowGet);
}

I like this solution because I have control of the Json in the controller, rather than forcing an object to always serialize the same way in all cases (sometimes I want the Item to serialize it’s Entries, but only when I’m getting a single Item).

Advertisement
This entry was posted in Uncategorized. Bookmark the permalink.

5 Responses to Handling Circular References ASP.NET MVC Json Serialization

  1. Jarrod Skulavik says:

    Funny again Mr. Bouman…I literally did the EXACT same thing yesterday, for the exact same reasons. My only fear is the cost (in memory) of creating so many anonymous types within each request. I’m now thinking dynamic types are maybe a little more efficient….em?

  2. Darin Lampson says:

    Interesting solution, in this scenario I use view models and AutoMapper. However, you end up doing a lot of maintenance on mapping logic. I tend to like to move the logic away from the controller. Another option is to push this aggregation to the db and use a view.

  3. steve says:

    you probably won’t like this idea either since you don’t want poco view models, but automapper makes it stupid easy to do.

    • steve says:

      and you’re basically just making anonymous poco view models the way you’re doing it. But the dynamic ness of how you’re doing it is attractive.

      • Dave Bouwman says:

        Right – it’s the same thing, but with a little more freedom. Not sure how this would scale up to “Twitter” but that’s a whole other bag of cats ;-)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s