c# – Serializar lista de objetos para JSON: A circular reference was detected while serializing an object of type

Question:

I'm trying to Serialize a list of objects to Json and have got the following error:

An exception of type

'System.InvalidOperationException' occurred in Microsoft.Web.Extensions.dll but was not handled in user code Additional information: A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Parents_FE2360F9C3DD9892003FC5DC33EF9BD07698CFF62033EE442867F74'C88F

I have used:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void GetListaPais(string prefixText, string contextKey)
{
    var serializer = new JavaScriptSerializer();
    var json = serializer.Serialize(AuxiliarControler.ListaPais(prefixText,contextKey));
    Context.Response.Clear();
    Context.Response.ContentType = "application/json";
    Context.Response.Flush();
    Context.Response.Write(json);
} 

Method that get the list of Pais :

public static List<Pais> ListaPais(string nomePais, int IDIdioma)
{
    using (entidadesIUS entidades = new entidadesIUS())
    {
        return entidades.Pais.Where(p => p.IDIdioma == IDIdioma && 
            p.Pais1.Contains(nomePais)).ToList();
    }
}

Entity Pais

public partial class Pais
{
    public Pais()
    {
        this.CAL = new HashSet<CAL>();
        this.Clientes = new HashSet<Clientes>();
    }

    public int IDPais { get; set; }
    public string Pais1 { get; set; }
    public int IDIdioma { get; set; }


    public virtual ICollection<CAL> CAL {get; set; }
    public virtual Idiomas Idiomas {get; set; } 
    public virtual ICollection<Clientes> Clientes {get; set; }
}

Answer:

This is because you possibly have an entity A that references an entity B and that somewhere goes back to referencing A.

To resolve, note the following on the dependent entities:

[JsonIgnore]
public virtual Idioma Idioma { get; set; }

Or, taking a global approach, it takes a little more work. This approach holds for the JSON.NET package .

1. Implement a JsonResult that uses the desired setting

Mine was like this:

public class CustomJsonResult : JsonResult
{
    private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        Formatting = Newtonsoft.Json.Formatting.Indented,
        ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    };

    public override void ExecuteResult(ControllerContext context)
    {
        if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
            string.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("GET request not allowed");
        }

        var response = context.HttpContext.Response;

        response.ContentType = !string.IsNullOrEmpty(this.ContentType) ? this.ContentType : "application/json";

        if (this.ContentEncoding != null)
        {
            response.ContentEncoding = this.ContentEncoding;
        }

        if (this.Data == null)
        {
            return;
        }

        response.Write(JsonConvert.SerializeObject(this.Data, Settings));
    }
}

2. Derive the Controller base class and implement an override for the Json method

public abstract class Controller : System.Web.Mvc.Controller
{
    protected override JsonResult Json(object data, string contentType, System.Text.Encoding contentEncoding, JsonRequestBehavior behavior)
    {
        return new CustomJsonResult
        {
            Data = data,
            ContentType = contentType,
            ContentEncoding = contentEncoding,
            JsonRequestBehavior = behavior
        };
    }
}

3. Test

I did a test to get 10 cities in my system that looked like this:

public async Task<JsonResult> SelecionarDez()
{
    var cidades = await db.Cidades.Take(10).ToListAsync();
    return Json(cidades, JsonRequestBehavior.AllowGet);
}
Scroll to Top