Wednesday, April 4, 2007

DataContractSerializer/XmlSerializer with circular object references

Recently we expirienced a problem when extending one of our current web services with WCF. We used NHibernate to retrieve the complex object from the database and as some of the child objects had references to their parents (and vice versa) - we used to break those via XmlIgnore attribute for XmlSerialization.
Though it seems that as default option for WCF is a DataContractSerializer, it behaves differently when XmlIgnore is encountered. It seems to simply ignore it, in the next step just throwing IndexOutOfRange exception, dropping the connection, which leads to the "System.ServiceModel.CommunicationException: The underlying connection was closed: The connection was closed unexpectedly. ---> System.Net.WebException: The underlying connection was closed: The connection was closed unexpectedly.." on the client, which is very, very throubleshooting unfriendly...
Our solution for a moment is to apply the [XmlSerializerFormat()] to the operation declaration (in the interface). That comes for the price of different proxy being produced with pretty messed up namespaces and classes, but it works for us and I expect it to be pretty backward-compatible with old clients (subject to test).
WCF configuration tool and service trace viewer tools from Windows Vista SDK helped quite a bit.
In the long run, we will just apply DataMember attributes appropriately to achieve the same result we have with XmlIgnore for XmlSerializer and then, we can return back to the DataContractSerializer.
Good reference to the simular problem with more info how to troubleshoot

UPDATE [24-Nov-2008] Now reading through msdn answer is found for the DataContractSerializer:
"Serializing object graphs as trees has certain disadvantages – for example, graphs with circular references cannot be serialized. Occasionally, it is necessary to switch to true object graph serialization, even though it is not interoperable. This can be done by using the DataContractSerializer constructed with the preserveObjectReferences parameter set to true." The best link I found, here: Also make sure you read this:

1 comment:

Anonymous said...

This just helped me find a serialization error that I couldn't see on client before applying this attribute. Thanks..