views:

1248

answers:

5

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".

For now, I'm removing the references in question, but ideally I'd like to simply mark the property such that the JSON serializer ignores it.

Can anyone suggest how I might do this?

+9  A: 

[ScriptIgnore] should work (untested)

Marc
This should work because a JsonResult uses the JavaScriptSerializer internally.
womp
Note to others: you may have to add a reference to the System.Web.Extensions assembly in order to make this available, at least in .NET 4.
Jacob
+7  A: 

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 <SCRIPT> 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.

Simon_Weaver
+1. At first I wanted to provide some backlash "I don't want to create multiple models", but you mention "view model" which is starting to make some sense to me: you make models for business logic, why not make models for view logic? Brilliant! Not the answer to my specific situation, but def worth an upvote.
JMP
i dont want to create multiple models either! this is the easiest way to do so without having to create another class (unnecessary here). the model should be the data and only the data, not how that data is displayed and while not always practical you should always minimize the coupling between view and model incase that view changes to a different technology or you need to provide multiple different views (ajax/flash/plain html)
Simon_Weaver
+2  A: 

I would advise to use JSON.NET. It allows to serialize circular references and provides much more serialization options.

Dmytrii Nagirniak
+1  A: 

What Simon said. Add a little AutoMapper action to keep code weight under control.

Wyatt Barnett
+1  A: 

I agree with Wyatt/Simon, MVVM all the way.

Family Friend