Tuesday 1 December 2009

WCF and serializing custom objects

I’ve been setting up an wcf service for a new n-tier system which I am currently architecting and developing at work. I’m trying to get to the point where all tiers store the data in the same objects (Entities) and they are worked on at different levels. These are simple POCO Entity objects which only store the data values and defined the data annotations to be used with validation. This will require the WCF service to be able to serialize the custom objects and transmit them between the tiers and in future, who knows maybe to a Silverlight client application as well?!

So, with the objects in place and with the correct DataContract and DataMember attributes in place I get the following error message when trying to pass them through the service between tiers:

“The underlying connection was closed: The connection was closed unexpectedly.”

After doing some Googling I came across the following blog post which had some handy pointers … thanks Bishoy Labib. But the biggest help was from a post by Damir Dobric. His post explaining how the "KnownTypeAttribute” is used when sending through data over a wcf service was very handy.

So after decorating the interface with each type of Entity I had which (3 so far) I built the project, got the service reference to update to get the latest definition and ran it with fingers crossed … it worked!

Damir had adding each of the types which might be used through the WCF service interface defined individually, then refactored it by adding them through the KnownTypeContainer (similar to below) and added them manually. This wouldn’t quite work for me as there are going to be, probably, lots of entities and I don’t want to have to add one individually each time. As all the entities are defined in a single project, I thought with a little reflection on the Assembly I could dynamically load them in so came up with this …

[ServiceKnownType("GetAllMyKnownTypes", typeof(KnownTypeContainer))] 
[ServiceContract(Namespace
= "http://mynamespace/2009/IApplication")]
public interface IApplication
{
[OperationContract]
string Echo(string value);

[OperationContract]
Entities.EntityBase Execute(
string action,
Dictionary
<string, object> parameters);
}

static class KnownTypeContainer
{
public static IEnumerable<Type>
GetAllMyKnownTypes(ICustomAttributeProvider p)
{
return new List<Type>(
Assembly.Load(
"Entities").GetTypes()
);
}
}




Nothing special, or clever, just need to make sure that all the Entities derive from the common EntityBase abstract class to work.



Thanks go to Damir for the original post and getting me through my issue I was having :-)

No comments: