WebApi Json Self referencing loop



我在 ASP.NET WebApi项目(完整的DotNet,而不是Core(中解决此错误时遇到了可怕的时间:

<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>Self referencing loop detected for property 'Server' with type 'System.Data.Entity.DynamicProxies.Server_8AB873452FD27AADAE6B91C89AF500FFD407544E56422B394D3E2B8AC1524157'. Path 'Server_Hardware_Current[0]'.</ExceptionMessage>
<ExceptionType>Newtonsoft.Json.JsonSerializationException</ExceptionType>
<StackTrace>   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at System.Web.Http.Results.JsonResult`1.Serialize()
at System.Web.Http.Results.JsonResult`1.Execute()
at System.Web.Http.Results.JsonResult`1.ExecuteAsync(CancellationToken cancellationToken)
at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)  at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()
</StackTrace>
</Error>

我必须补充并强烈强调我是 c# 的菜鸟。 如果您需要更多信息,请告诉我您到底需要什么,如果您希望我将 core 放入文件中,请告诉我文件名;)

关于我的项目:

我正在尝试创建一个客户端/服务器解决方案,该解决方案将在目标服务器/客户端上部署代理,并将其硬件和软件发送到中央数据库,就像每个软件部署软件一样。 代理本身可以从系统中读取所需的信息,因此我现在正在尝试创建 WebApi,该 WebApi 将接受结果并为代理提供通信端点以及某种控制台以查看信息并进行不同类型的评估(我的系统是最新的吗?哪个软件安装在何处等等(。

使用的软件和软件包

我正在运行Visual Studio 2017社区

Nuget 包:

  • 默认的WebApi包(包括Newtonsoft.json(
  • 实体框架 6,还创建了一个模型 EDMX 文件,它看起来 对我来说很正确
  • 用于日志记录的企业库

控制器代码部分

public IHttpActionResult GetSingleServer(int id)
{
// using (KysoHostDbContext ServersDbContext = new KysoHostDbContext())
// {
KysoHostDbContext ServersDbContext = new KysoHostDbContext();
//ServersDbContext.Configuration.ProxyCreationEnabled = false;
//ServersDbContext.Configuration.LazyLoadingEnabled = false;

var returnobject = ServersDbContext.Servers.FirstOrDefault(a => a.ServerId == id);
// .Include(ServersDbContext.Servers.FirstOrDefault().Server_OS_Current.ToString());

if ((returnobject.Equals(null)))
{
return NotFound();
}
else
{
return Json(returnobject);
}
// }
}

模型

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace KysoWebApi.Models
{
public partial class Servers
{
public Servers()
{
ServerHardwareCurrent = new HashSet<ServerHardwareCurrent>();
ServerHardwareHistory = new HashSet<ServerHardwareHistory>();
ServerOsCurrent = new HashSet<ServerOsCurrent>();
ServerOsHistory = new HashSet<ServerOsHistory>();
ServerWinFeaturesCurrent = new HashSet<ServerWinFeaturesCurrent>();
ServerWinFeaturesHistory = new HashSet<ServerWinFeaturesHistory>();
ServerWinInstalledSoftwareCurrent = new HashSet<ServerWinInstalledSoftwareCurrent>();
ServerWinInstalledSoftwareHistory = new HashSet<ServerWinInstalledSoftwareHistory>();
ServerWinRolesCurrent = new HashSet<ServerWinRolesCurrent>();
ServerWinRolesHistory = new HashSet<ServerWinRolesHistory>();
}
[Key]
public int ServerId { get; set; }
[Required]
[Column(TypeName = "varchar(50)")]
public string AgentGuid { get; set; }
[InverseProperty("Server")]
public ICollection<ServerHardwareCurrent> ServerHardwareCurrent { get; set; }
[InverseProperty("Server")]
public ICollection<ServerHardwareHistory> ServerHardwareHistory { get; set; }
[InverseProperty("Server")]
public ICollection<ServerOsCurrent> ServerOsCurrent { get; set; }
[InverseProperty("Server")]
public ICollection<ServerOsHistory> ServerOsHistory { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinFeaturesCurrent> ServerWinFeaturesCurrent { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinFeaturesHistory> ServerWinFeaturesHistory { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinInstalledSoftwareCurrent> ServerWinInstalledSoftwareCurrent { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinInstalledSoftwareHistory> ServerWinInstalledSoftwareHistory { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinRolesCurrent> ServerWinRolesCurrent { get; set; }
[InverseProperty("Server")]
public ICollection<ServerWinRolesHistory> ServerWinRolesHistory { get; set; }
}
}

我已经尝试过了

我一直在阅读日志并尝试了很多不同的解决方案,但奇怪的是,它们都不适合我。 正因为如此,我想这是某种非常愚蠢的新手错误-.- 当然,我已经单独尝试了所有这些解决方案(现已注释掉(。

  • 全球

    /*
    var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    json.SerializerSettings.PreserveReferencesHandling =
    Newtonsoft.Json.PreserveReferencesHandling.All;
    */
    
    /*
    HttpConfiguration config = GlobalConfiguration.Configuration;
    config.Formatters.JsonFormatter
    .SerializerSettings
    .ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    */
    /*
    JsonConvert.DefaultSettings = () => new JsonSerializerSettings
    {
    Formatting = Newtonsoft.Json.Formatting.Indented,
    ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
    };
    */
    
  • WebApiConfig.cs

    /*
    config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
    = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    */
    
    /*
    config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling
    = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
    config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling
    = Newtonsoft.Json.PreserveReferencesHandling.Objects;
    */
    /*
    * var json = config.Formatters.JsonFormatter;
    json.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
    */
    
  • 服务器控制器.cs

正如您可能在控制器代码中看到的那样,我尝试显式禁用延迟加载,因为我的模型包含虚拟指令。由于删除它没有帮助,我尝试禁用延迟加载,这仍然导致相同的错误。 仅当我禁用代理创建时,我才会得到一个结果,但这只包括服务器表中的 SQL 数据,而不是我想要的所有子对象。 这可能不是一直都需要的,但请耐心等待,因为我以后无论如何都需要它。

我还尝试使用类似使用 .包括,但我未能让它工作。 我的感觉是:

public IHttpActionResult GetSingleServer(int id) 

可能是一个问题,但我无法使用

return NotFound();

或:

return Json(returnobject);

任何帮助将不胜感激。 另外,提前感谢任何花时间阅读所有这些:)


更新 1

我试过了: ' public IHttpActionResult GetSingleServer(int id( {

// using (KysoHostDbContext ServersDbContext = new KysoHostDbContext())
// {
KysoHostDbContext ServersDbContext = new KysoHostDbContext();
// ServersDbContext.Configuration.ProxyCreationEnabled = false;
ServersDbContext.Configuration.LazyLoadingEnabled = false;

var returnobject = ServersDbContext.Servers.Include("ServerHardwareCurrent")
.Where(a => a.ServerId == id);
// .Include(ServersDbContext.Servers.FirstOrDefault().Server_OS_Current.ToString());

if ((returnobject.Equals(null)))
{
ServersDbContext.Dispose();
return NotFound();
}
else
{
ServersDbContext.Dispose();
return Json(returnobject);
}
// }
}`

这给了我:

<ExceptionMessage>The operation cannot be completed because the DbContext has been disposed.</ExceptionMessage><ExceptionType>System.InvalidOperationException</ExceptionType><StackTrace>   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()   at System.Data.Entity.Internal.Linq.InternalQuery`1

我明确禁用了延迟加载,但它仍然尝试延迟加载?

如果我尝试移动它,结果相同:var returnobject = ServersDbContext.Servers.Where(a => a.ServerId == id(。包括("服务器硬件当前"(;

这让我发疯。 为什么它总是延迟加载,即使我告诉它不要这样做? :/

由于没有更多评论,这是我的解决方案。请用一粒盐服用:

关于我的关系循环问题,我发现如果我删除与服务器表相关的所有表的导航属性,它就可以工作。不过,我必须将它们留在服务器桌上。这实际上并没有解决 Json 不关心我告诉它忽略循环的问题,但它删除了循环,至少我的代码可以工作。

最新更新