How to crash a WCF Service

As part of a recent project, I needed to create a WCF service, host it in IIS and then access it through a remote client.  The client in this case implemented an interface that would allow the client to connect to other sites as well- the concrete implementation of the interface dealing with all the data.

There were common DTOs being used on the client side, and since I had complete control over both the client and server side code, I thought I would try to use RIA’s DomainService in a non-RIA app, to pull entities from the database, convert them to the common DTO type and then send them across the wire to the client.

Everything was off to a great start and then I noticed that after one particular (or so I thought) request, the WCF service was completely locked up.  I had to either recompile my service or restart IIS with iisreset to get things working again.

The errors were quite painful to track down.  Data was returned to the client just fine on the first call- but subsequent calls failed with the following exception:

System.ServiceModel.CommunicationException.

After enabling WCF Tracing (http://msdn.microsoft.com/en-us/library/ms733025.aspx) I saw the following error:

The InnerException  message was ‘Type ‘System.Globalization.GregorianCalendar’ with data  contract name
‘GregorianCalendar:http://schemas.datacontract.org/2004/07/System.Globalization’
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.’. Please
see InnerException for more details.

After some head scratching, concluding the error wasn’t informative, scouring the net etc., etc., I found the following post:

http://howevangotburned.wordpress.com/2007/12/06/type-fidelity-across-the-wire-in-wcf/

Turns out you can’t sent abstract or virtual types over WCF!  Whoops.  In one of my objects, I was sending a CultureInfo object, which has a Calendar member.  And while calendar is virtual, the concrete implementation being sent was a GregorianCalendar.

In my case, the fix would have been pretty easy

[DataContract] 
[KnownType( typeof( CircleType ) )] 
[KnownType( typeof( TriangleType ) )] 
public class CompanyLogo2 
{ 
    [DataMember] 
    private Shape ShapeOfLogo; 
    [DataMember] 
    private int ColorOfLogo; 
}

Use the KnownType attribute.  But in other cases, like with System.Type, these are internal and you are basically out of luck.

So I ended up NOT sending my object, but rather just sending generated Entity objects- as these seem to be safer than what I could put together to send and crash WCF.