C# – Se detectó una referencia circular al serializar un objeto

publicado por: Anonymous

Estoy desarrollando una aplicación aspnet mvc5 y EF , tengo los modelos a partir de la BD en concreto tengo esto que es para los tipos de productos que tienen más articulos

namespace testweb.Models
{
    using System;
    using System.Collections.Generic;

    public partial class TipoProductos
    {
        public TipoProductos()
        {
            this.Articulos = new HashSet<Articulos>();
        }

        public short tipoProducto { get; set; }
        public string Familia { get; set; }
        public string Descripcion { get; set; }
        public string activo { get; set; }
        public Nullable<byte> iva { get; set; }

        public virtual ICollection<Articulos> Articulos { get; set; }
    }
}

Luego tengo en el controlador para devolver un JSON con los distintos registros de este modelo

public JsonResult getProductCategories()
{
    List<TipoProductos> categorias = new List<TipoProductos>();
    categorias = db.TipoProductos.OrderBy(a => a.Descripcion).ToList();
    return new JsonResult { Data = categorias, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}

Y el archivo JS desde donde hago la petición

var CategoriasProductos = []

//obtener categorias desde la BD
function LoadCategory(element) {
    if (CategoriasProductos.length == 0) {
        $.ajax({
            type: "GET",
            url: '/Ventas/getProductCategories',
            success: function (data) {
                CategoriasProductos = data;
                renderCategory(element);
            },

            error: function (error) {
                console.log('*** error   --> ' + error.responseText);
            },

        })
    }
    else {
        renderCategory(element);
    }
}

El error que recibo al hacer la petición al controlador es este

Se detectó una referencia circular al serializar un objeto de tipo ‘System.Data.Entity.DynamicProxies.Articulos

¿Cuál es la mejor forma para solucionar esto? Leyendo he visto que se puede hacer poniendo el atributo ScriptIgnore en el modelo. ¿Qué me recomendáis?


Modelo Articulos:

namespace testweb.Models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.Runtime.Serialization;
    using System.Web.Script.Serialization;

    [DataContract(IsReference = true)]
    public partial class Articulos
    {
        public Articulos()
        {
            this.AlbaranesLinias = new HashSet<AlbaranesLinias>();
            this.ArticulosHistoricoPrecios = new HashSet<ArticulosHistoricoPrecios>();
            this.Stock = new HashSet<Stock>();
            this.VentasLinias = new HashSet<VentasLinias>();
        }


        public string weblogin { get; set; }
        public byte tienda { get; set; }
        public int id { get; set; }
        public short proveedor { get; set; }


        [ScriptIgnore]
        public virtual ICollection<AlbaranesLinias> AlbaranesLinias { get; set; }
        [ScriptIgnore]
        public virtual Proveedores Proveedores { get; set; }
        [ScriptIgnore]
        public virtual ICollection<ArticulosHistoricoPrecios> ArticulosHistoricoPrecios { get; set; }
        [ScriptIgnore]
        public virtual ICollection<Stock> Stock { get; set; }
        [ScriptIgnore]
        public virtual ICollection<VentasLinias> VentasLinias { get; set; }
        [ScriptIgnore]
        public virtual TipoProductos TipoProductos { get; set; }
    }
}

Modelo tipoProductos:

namespace testweb.Models
{
    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Runtime.Serialization;
    using System.Web.Script.Serialization;

    [DataContract(IsReference = true)]
    public partial class TipoProductos
    {
        public TipoProductos()
        {
           this.Articulos = new HashSet<Articulos>();
        }

        public short tipoProducto { get; set; }
        public string Familia { get; set; }
        public string Descripcion { get; set; }
        public string tipo1 { get; set; }
        public string tipo2 { get; set; }
        public string tipo3 { get; set; }
        public string activo { get; set; }
        public Nullable<byte> iva { get; set; }

        //[ScriptIgnore]
        public virtual ICollection<Articulos> Articulos { get; set; }

    }
}

He puesto el código que me has puesto del JsonResult de getProductCategories y me devuelve este error:

Error 1 No se puede convertir implícitamente el tipo
‘System.Collections.Generic.List’ en
‘System.Collections.Generic.List’


Me faltaría hacer que el resultado esté agrupado por los campos Familia para ello pongo este código:

public JsonResult getProductCategories()
    {
        var categorias = db.TipoProductos.OrderBy(a => a.Descripcion)
                            .GroupBy(p => p.Familia)
                            .Select(c => new { Descripcion = c.Descripcion, Familia = c.Familia, TipoProducto = c.tipoProducto, Activo = c.activo })
                            .ToList();
        return new JsonResult { Data = categorias, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
    }

Pero si intento agrupar por el campo Familia me da este error

`Error 4 ‘System.Linq.IGrouping’
no contiene una definición de ‘activo’ ni se encontró ningún método
de extensión ‘activo’ que acepte un primer argumento de tipo
‘System.Linq.IGrouping’ (¿falta
una directiva de uso o una referencia de ensamblado?).

solución

Si añades [DataContract(IsReference = true)] al principio de tus clases de datos TiposProducts y Articulos evitarás ese fallo al serializar por referencia cíclica.

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *