代码之家  ›  专栏  ›  技术社区  ›  Alex Varela

asp中的即时加载。net web api

  •  1
  • Alex Varela  · 技术社区  · 7 年前

    大家好,我最近开始学习如何编写web api,

    我在winform中有一个项目,我想使用web api重新制作,但我不能使用即时加载,我总是会遇到错误500,代码如下:

    public HttpResponseMessage GetExpediente()
        {
            db.Configuration.ProxyCreationEnabled = false;
            var expediente = db.Expediente.Include(x=>x.Documento);
            if (expediente.Any())
            {
                return Request.CreateResponse(HttpStatusCode.OK, expediente);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                    "No se encontraron expedientes.");
            }
        }
    

    我经常遇到的错误是:

    {"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected for property 'Expediente' with type 'Modelo.Expediente'. Path '[0].Documento[0]'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":"   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   en Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   en System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- Fin del seguimiento de la pila de la ubicación anterior donde se produjo la excepción ---\r\n   en System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   en System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   en System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"}}
    

    我一直在寻找信息。这可能对我有帮助,但我总是发现我应该禁用懒散加载,我做到了,但它没有起作用,这里有人能帮我吗?

    顺便说一句,我的目标是从windows窗体项目中使用此api,有人告诉我这样做:

    var emp1 = response.Content.ReadAsStringAsync().Result;
            var result = JsonConvert.DeserializeObject<IEnumerable<ExpedientePOCO>>(emp1);
    

    但是我从var emp1=。。。是错误500。哦,当我从上下文中获取include时,它工作得很好,但我想使用渴望加载,希望你能帮助我!

    谢谢当做

    我对DTO的理解:

     public HttpResponseMessage GetExpediente()
        {
            db.Configuration.ProxyCreationEnabled = false;
            var expediente = db.Expediente.Include(x=>x.Documento);
            List<ExpedientePOCO> expPOCO = new List<ExpedientePOCO>();
            foreach (var entidad in expediente)
            {
                String fecha = String.Format("{0:dd-MM-yyy}", entidad.FechaCreacion);
                ExpedientePOCO expedientePOCO = new ExpedientePOCO()
                {
                    idExpediente = entidad.idExpediente,
                    NombreExpediente = entidad.NombreExpediente,
                    FechaCreacion = Convert.ToDateTime(fecha),
                    DuenioExpediente = entidad.DuenioExpediente,
                    CantidadDocumento = entidad.CantidadDocumento
                };
                foreach (var documentos in entidad.Documento)
                {
                    DocumentoPOCO documento = new DocumentoPOCO()
                    {
                        idDocumento = documentos.idDocumento,
                        idExpediente = documentos.idExpediente,
                        NombreDocumento = documentos.NombreDocumento,
                        FechaCreacion = documentos.FechaCreacion,
                        Expedientes = expedientePOCO
                    };
                    expedientePOCO.Documentos.Add(documento);
                }
                expPOCO.Add(expedientePOCO);
            }
            if (expPOCO.Any())
            {
                return Request.CreateResponse(HttpStatusCode.OK, expPOCO);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                    "No se encontraron expedientes.");
            }
        }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Camilo Terevinto Chase R Lewis    7 年前

    问题是,正如错误消息所述,您有一个无休止的循环,很可能是这样的:

    public class A
    {
        public B B { get; set; }
    }
    
    public class B
    {
        public virtual ICollection<A> A { get; set; }
    }
    

    所以你得到 A => B => A 无休止地,因此出现了错误。您可以通过配置序列化程序来解决此问题( ReferenceLoopHandling.Ignore 在NewtonSoft中。Json),或使用属性( [JsonIgnore] ),具体取决于您的具体需要和使用的工具。

    另一种解决方案是使用数据传输对象(DTO)或类似对象:

    public class ADTO
    {
        // needed properties only
        public BDTO B { get; set; }
    }
    
    public class BDTO
    {
        // needed properties only
        public List<ADTO> A { get; set; }
    }
    

    然后选择进入DTO而不是实体:

    var data = db.As
        .Select(a => new ADTO 
        {
            x = a.x ....
            B = new BDTO { x = a.B.x ...  }
        }
        .ToList();
    

    或者,反过来说:

    var data = context.B
        .Select(b => new BDTO
        {
            x = b.x ...
            A = b.A
                .Select(a => new ADTO
                {
                    x = a.x ...
                }
                .ToList()
        }
        .ToList();