While developing an ASP.NET MVC app, I\'m finding a few places where my JsonResult actions throw an exception \"A circular reference was detected while serializing an object\".<
What Simon said. Add a little AutoMapper action to keep code weight under control.
I've generally found that for complex objects its best to just serialize by creating a temporary 'inbetween' object :
For instance for testimonials I do the following. I actually do this in the codebehind for my ASPX model page.
This creates a nice JSON object. You'll notice I can even refactor my model and the page will still work. Its just another layer of abstraction between the data model and the page. I dont think my controller should know about JSON as much as possible, but the ASPX 'codebehind' certainly can.
/// <summary>
/// Get JSON for testimonials
/// </summary>
public string TestimonialsJSON
{
get
{
return Model.Testimonials.Select(
x => new
{
testimonial = x.TestimonialText,
name = x.name
}
).ToJSON();
}
}
In my ASPX I just do this in a block:
var testimonials = <%= TestimonialsJSON %>;
// oh and ToJSON() is an extension method
public static class ObjectExtensions
{
public static string ToJSON(this Object obj)
{
return new JavaScriptSerializer().Serialize(obj);
}
}
I'm ready for the backlash against this suggestion... bring it on...
I'm not accessing data, merely reformatting a model for the View. This is 'view model' logic, not 'controller model' logic.
[ScriptIgnore] should work for you.
I would advise to use JSON.NET. It allows to serialize circular references and provides much more serialization options.
The cleanest approach i've found is to use a combination of [DataContract] on the class and [DataMember] on the properties you want to serialize. The DataContract attribute tells the various serializers to ignore any property that doesn't have the DataMember attribute.
There are two major benefits compared to using ScriptIgnoreAttribute. First, it doesn't have a dependency on the System.Web.Extensions assembly. Second, it works with other types of serialization, not just JSON. For example, if you're using the new Web API in MVC 4, the DataContract/DataMember approach will work with the XML serializer as well.
Consider the scenario where your entities are stored in an shared library and reused across various projects - you don't want a dependency on System.Web.Extensions, and you want to loosely describe serialization rules - not hardcode behavior specific to JSON, XML, etc.