WCF Serialization Issue
I really need to learn more about WCF.
I recently had a problem with serializing my business objects when trying to send to a WCF web service. The fix was the most simple thing in the world but it took me a considerable amount of time to discover it because I thought the problem was something else which led to a whole bunch of unnecessary changes which made matters worse…you know how the story goes :-)
This is the lovely errror I was getting when calling my Save method on my web service:-
System.Runtime.Serialization.SerializationException: Type ‘System.DelegateSerializationHolder+DelegateEntry‘ with data contract name ‘DelegateSerializationHolder.DelegateEntry:http://schemas.datacontract.org/2004/07/System’ is not expected. 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.
- what was I trying to do
- what caused the problem
- and what was the (annoyingly simple) fix??
First of all, I setup up a pretty much ‘out of the box’ WCF web service with a couple of simple changes shown here (You can download the sample project (with some dummy biz objects etc) here.)
(The relevant part is I’m reusing the types in the Biz assembly client side and server side.)
So just briefly, architecturally I have a Biz project which is referenced by my WCF Service and my client side Service Access Layer (SAL). My unit Test project is my ‘client’ in this case and is referencing both the SAL and Biz projects.
What I was trying to do was save a ‘Dog’ (one of my biz classes) using the web service. This Dog class looks something like this:
So what, in this most simple of classes, was causing my serialization issue? The combination of two things…
- The [Serializable] attribute
- and the FetchingBall event
When I create a new Dog and do NOT add a handler for FetchingBall, the Dog serialized to and from the WCF service no problems at all. Once you add an event handler….boom, the nice SerializationException occurs.
Now my ‘real’ biz objects implement INotifyPropertyChanged so 99% of the time there will be handlers and so 99% of the time they would fail to be serialized…not particularly useful!
Mark your object with the [DataContract] attribute.
Well Ok you also need to now mark all of your properties/fields that you want to be included in the serialization with the [DataMember] attribute as using the DataContractSerializer is an ‘opt-in’ approach.
You can take off the [Serializable] attribute or you may have them both. Personally I want my Biz objects to be serializable in case I want to save them client side.
If you want to see this in action just download the test project. The first two tests in Tests.cs are the important ones. It is currently setup so the second one will fail (as it registers a handler for the event).
Try it and then try uncommenting the [DataContract] attribute on the Dog class, then run them again and the second one should also work!