Serialize object list for JSON: A circular reference was detected while serializing an object of type

8

I'm trying to Serialize a list of objects to Json and I have received 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.Pais_FE2360F9C3DD9892003FC5DC33EF9BD07698CFF62033EE442867F74C88F09AC7'.

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 gets 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; }
}
    
asked by anonymous 07.10.2014 / 15:36

2 answers

16

This happens because you possibly have an entity A that references an entity B and somewhere it references A again.

To resolve, note the following on dependent entities:

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

Or, in a global approach, it does a little more work. This approach holds true for the JSON.NET package .

1. Implement a JsonResult that use the desired setting

My looks 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 base class Controller and implement a override for the method Json .

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 ran a test to get 10 cities on my system that looked like this:

public async Task<JsonResult> SelecionarDez()
{
    var cidades = await db.Cidades.Take(10).ToListAsync();
    return Json(cidades, JsonRequestBehavior.AllowGet);
}
    
07.10.2014 / 19:11
9

I recommend using from this library . It is highly widespread in the .NET community. In my case I use the resource below to avoid cyclic references and ignore null values in json at the time of serialization.

 GlobalConfiguration.Configuration.Formatters.JsonFormatter
    .SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

 GlobalConfiguration.Configuration.Formatters.JsonFormatter
    .SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;

This configuration is done in the Global.asax file of a WebApi application. You would have to see in your case where to put it.

    
08.10.2014 / 02:47