Serialize object list for JSON: A circular Reference was Detected while serializing an Object of type

Asked

Viewed 9,392 times

8

I’m trying to Serialize a list of objects to Json and 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’ve been using:

[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 obtaining 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; }
}
  • 1

    "Gives dick" is the most subjective comment possible. What is the mistake? What have you tried to do to Ana it?

  • What is the IDE you are using?

2 answers

18


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

To solve, write down the following in the dependent entities:

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

Or, in a global approach, it takes a little more work. This approach applies to 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 basic 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. Testing

I took 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);
}
  • 2

    Beautiful magnification of the answer, very good.

  • 1

    Truth @Marconi ! I implemented in a project and ran perfectly!

  • 2

    @Mauríciojúnior This response from the Gypsy is sensational. Good that she can help you :)

  • I am struggling to implement this solution, I imagine that in Controller I must replace: public class ColaboradorController : Controller for public class ColaboradorController : CustomJsonResult , that’s it ?

  • Not. CustomJsonResult is a class. Controller derivative of System.Web.Controller is another.

  • I understand, but how do I implement the use of this class in my Controller? The Controller contains some ActionResult and JsonResult, example: public JsonResult MontarGridColaborador() that return data from BD (return with circular reference) and want to implement this solution to display the data in View.

  • No, the class is separate from the Controller. The Controller implementing public JsonResult MontarGridColaborador() will he inherit from Controller and the circular reference problem ends because this Controller ancient reimplementa JsonResult.

  • 2

    Okay! , after I saved the classes inside the briefcase Controller and it worked, perfect!

  • In my case it is giving the following Message: 'Controller' is an ambiguos Reference between 'ERP4.Helpers.Controller' and 'System.Web.Mvc.Controller' how do I Declare this new controller without conflicting with the Mvc default?

  • @Edenilsonbile public abstract class Controller: System.Web.Mvc.Controller { ... }

Show 5 more comments

9

I recommend the use of this library. It is highly widespread in the .net. 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 setting is done in the Global.asax file of a Webapi application. You would have to see in your case where to put it.

  • He is already using JSON.NET. Possibly at the time I had to resolve this configuration didn’t even exist. + 1.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.