I have some POCO objects that are set up for use with Entity Framework Code First.
I want to return one of those objects from an ApiController in my ASP.NET MVC 4 website, and then consume it in a client application.
I originally had problems with the serialization of the object at the server end, because the Entity Framework was getting in the way (see Can an ApiController return an object with a collection of other objects?), and it was trying to serialize the EF proxy objects rather than the plain POCO objects. So, I turned off proxy generation in my DbContext to avoid this - and now my serialized objects look OK (to my eye).
The objects in question are "tags" - here's my POCO class:
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; }
}
Pretty standard stuff, but note the ClientId and Client members. Those are EF Code First "navigation" properties. (Every tag belongs to exactly one client).
Here's what I get from my 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>
The Client member is nil because having disabled proxy generation I don't get automatic loading of the referenced objects. Which is fine, in this case - I don't need that data at the client end.
So now I'm trying to de-serialize those objects at the client end. I had hoped that I would be able to re-use the same POCO classes in the client application, rather than create new classes. DRY and all that. So, I'm trying:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Tag));
var tag = xmlSerializer.Deserialize(stream);
But I've run into two problems, both of which are due to EF Code First conventions:
Problem 1: Because my Tag class has a Client member, the XmlSerializer is complaining that it doesn't know how to de-serialize that. I guess that's fair enough (though I had hoped that because the member was Nil in the XML it wouldn't care). I could pass in extra types in the XmlSerializer constructor, when I tried that, it then complained about other classes that Client uses. Since Client references all sorts of other objects, I'd end up having to pass in them all!
I tried using the [DataContract] and [DataMember] attributes to remove the Client member from the XML (by not marking it as a DataMember). That did remove it from the XML, but didn't stop the XmlSerializer from whining about it. So I guess it's not the fact that it's in the XML that's the problem, but that it's in the class definition.
Problem 2: When I did try passing in typeof(Client) as an extra type, it also complained that it couldn't de-serialize that class because it contains an interface member. That's because - again due to EF Code First conventions - it has a Tags member as follows:
`public virtual ICollection<Tag> Tags { get; set; }`
So it looks like even if I get over the referenced-types problem, I'm still not going to be able to use my POCO classes.
Is there a solution to this, or do I have to create new DTO classes purely for use at the client side, and return those from my ApiController?