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);
}