如何从ApiController反序列化数据

时间:2012-08-01 13:47:52

标签: serialization asp.net-mvc-4 asp.net-web-api entity-framework-5

我有一些POCO对象设置为与Entity Framework Code First一起使用。

我想从ASP.NET MVC 4网站的ApiController返回其中一个对象,然后在客户端应用程序中使用它。

我最初在服务器端序列化对象时遇到问题,因为实体框架正在阻碍(参见Can an ApiController return an object with a collection of other objects?),并且它试图序列化EF代理对象而不是普通的POCO对象。所以,我在我的DbContext中关闭代理生成以避免这种情况 - 现在我的序列化对象看起来很好(我的眼睛)。

有问题的对象是“标签” - 这是我的POCO课程:

public class Tag
{
    public int Id { get; set; }

    public int ClientId { get; set; }
    public virtual Client Client { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public bool IsActive { get; set; }
}

非常标准的东西,但请注意ClientId和Client成员。这些是EF Code First“导航”属性。 (每个标签只属于一个客户端)。

这是我从ApiController获得的内容:

<Tag xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Foo">
  <Client i:nil="true"/>
  <ClientId>1</ClientId>
  <Id>1</Id>
  <IsActive>true</IsActive>
  <Name>Example</Name>
</Tag>

客户端成员为零,因为禁用代理生成我没有自动加载引用的对象。这种情况很好,在这种情况下 - 我不需要客户端的数据。

所以现在我正在尝试在客户端对这些对象进行反序列化。我希望我能够在客户端应用程序中重用相同的POCO类,而不是创建新的类。干,等等。所以,我正在努力:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(Tag));

var tag = xmlSerializer.Deserialize(stream);

但是我遇到了两个问题,这两个问题都归因于EF Code First惯例:

问题1 :因为我的Tag类有一个Client成员,所以XmlSerializer抱怨说它不知道如何反序列化它。我认为这是公平的(虽然我曾希望因为该成员在XML中是Nil而不关心)。我可以在XmlSerializer构造函数中传递额外的类型,当我尝试它时,它然后抱怨客户端使用的其他类。由于客户端引用了各种其他对象,我最终都要传递所有这些对象!

我尝试使用[DataContract]和[DataMember]属性从XML中删除Client成员(不将其标记为DataMember)。这确实将它从XML中删除了,但并未阻止XmlSerializer对它抱怨。所以我想这并不是因为它是XML中的问题,而是它在类定义中。

问题2 :当我尝试将typeof(Client)作为额外类型传递时,它还抱怨它无法对该类进行反序列化,因为它包含一个接口成员。这是因为 - 再次由于EF Code First约定 - 它有一个Tags成员如下:

`public virtual ICollection<Tag> Tags { get; set; }`

所以看起来即使我克服了引用类型的问题,我仍然无法使用我的POCO类。

是否有解决方案,或者我是否必须创建纯粹在客户端使用的新DTO类,并从我的ApiController返回它们?

1 个答案:

答案 0 :(得分:0)

我刚尝试使用DataContractSerializer代替XmlSerializer,而对于似乎有用的Tag类。我还没有尝试使用具有虚拟ICollection<T>成员的类......

更新:尝试过,它“有效”。它仍然设法重建对象,并将ICollection成员保留为null。

更新2:好的,结果证明是死路一条。是的,这意味着我可以正确地序列化和反序列化类,但是每个人都告诉我,DTO课程是更好的方法。 (DTO =数据传输对象 - 专门为通过线路传输数据而创建的类,可能包含原始字段的子集)。

我现在正在使用AutoMapper(感谢Cuong Le),以便我可以轻松地将我的POCO实体转换为更简单的DTO类进行序列化,这就是我建议面对同样的人问题