ASP.NET API序列化具有循环依赖关系的实体

时间:2015-07-30 20:53:55

标签: c# asp.net serialization

我有Test个实体和User个实体。

测试:

public class Test
{
  public int Id {get; set;}
  public string Title {get; set;}
  ...
  public virtual IList<User> Users {get; set;}
}

用户:

public class User
{
  public int Id {get; set;}
  public string Name {get; set;}
  ...
  public virtual IList<Test> Tests {get; set;}
}

在我的TestsApiController中,我有以下行动:

public IQueryable<Test> GetTests()
{
    return db.Tests;
}

这会返回一个序列化异常,因为它会尝试循环序列化User个对象,然后是Test个对象,然后是User个对象,依此类推。

我目前的计划是创建一个TestDTO,其中包含IList<int> UserIds而不是实际的对象。然后我将在序列化之前将所有Test对象转换为TestDTO对象,这有点令人讨厌。然后,如果我想要使用循环依赖关系序列化其他实体,我将不得不为它们创建更多的数据传输对象。

有没有办法创建或配置序列化程序,以便在此上下文中自动将User(或任何其他)对象序列化为Id属性?

以异常编辑: 无论是使用XML还是JSON

,我都会遇到相同的异常
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
</ExceptionMessage>
<ExceptionType>System.InvalidOperationException</ExceptionType>
<StackTrace/>
<InnerException>
<Message>An error has occurred.</Message>
<ExceptionMessage>
Type 'System.Data.Entity.DynamicProxies.Test_6585C5F85A384907958ABA03B661933EF718BDEDE1513392E060DE06E80DB552' with data contract name 'Test_6585C5F85A384907958ABA03B661933EF718BDEDE1513392E060DE06E80DB552:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
</ExceptionMessage>
<ExceptionType>
System.Runtime.Serialization.SerializationException
</ExceptionType>
<StackTrace>...</StackTrace>
</InnerException>
</Error>

2 个答案:

答案 0 :(得分:2)

构造json结果的一种非常简单的方法是使用NewtonSoft json序列化程序中的JObject(这通常是ASP.NET Web Api中的默认值)。你要找的东西看起来像

public JObject GetTests()
{

    NewtonSoft.Json.Linq.JObject jsonResult = NewtonSoft.Json.Linq.JObject.FromObject(new 
    {
        Tests = from test in db.tests
                select new 
                {
                    Id = test.Id,
                    Title = test.Title,
                    Users = from user in test.Users
                            select new
                            {
                                Id = user.Id
                            }
                }
    });

    return jsonResult;
}

这使您可以更好地控制json结果,以便您可以选择要序列化的字段/属性,并避免创建大量数据传输对象。希望这会有所帮助。

干杯

答案 1 :(得分:1)

在您的网络api配置(App_Start / WebApiConfig.cs)中,添加以下内容:

    public static class WebApiConfig
    {
      public static void Register(HttpConfiguration config)
      {
        // Prevent "Self referencing loop detected" error occurring for recursive objects
        var serializerSettings = new JsonSerializerSettings()
        {
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore
        };
        config.Formatters.JsonFormatter.SerializerSettings = serializerSettings;
      }
    }

这告诉JSON.NET忽略引用回父对象的嵌套对象