Tuesday, October 30, 2007

Serializing Cyclic LINQ to SQL References with WCF

Rick Strahl observes in his WCF and segmented WSDL Files = Problems post of October 30, 2007 that the Web Service Definition Language (WSDL) documents generated by Windows Communication Foundation (WCF) Web services include a <wsdl:import namespace="someNamespace" location="uRLforWSDL"> element.

He found that several Web Service clients, such as Microsoft's SOAP Toolkit, some scripting clients and Adobe Flex's WSDL Import Wizard have problems reading WSDLs that use the wsdl:import feature. The .Net wsdl:import problem when parsing a wsdl made with websphere / java thread from the ASMX Web Services and XML Serialization forum indicates that .NET 2.0's Wsdl.exe implementation has a problem importing WSDL documents. (See especially the last post dated September 17, 2007.)

The Web Service Interoperability Council's WS-I Web Services Basic Profile 1.0 and later versions make specific reference to the wsdl:import feature, which is used to import other WSDL documents. Although all "modern" Web service clients should be able to handle WSDL imports, Rick contents that WCF should provide a "self-contained WSDL" option for maximum interoperability. I agree.

You can avoid the wsdl:import issue by creating .asmx services, which don't concatenate WSDL documents. However, Rick notes that you need to use WCF's DataContractSerializer to avoid serialization failures when the standard XmlContractSerializer encounters a circular reference (cycle).

I've been working on emulating the missing "mini connectionless DataContext" to enable a multi-tier, service-based architecture for LINQ to SQL. (See the "Emulating the Phantom Mini Connectionless DataContext" section of my LINQ to SQL Has No "Out-of-the-Box Multi-Tier Story!" post of October 18, 2007. LINQ to SQL marks public properties, including EntitySet (1:n) associations, as DataMembers but not EntityRef (m:1) associations to prevent circular references. It's my understanding that the DataContractSerializer requires setting the preserveObjectReferences parameter to true to support bidirectional serialization. Here's a response to the System.ServiceModel.CommunicationException - The socket connection was aborted... question in the WCF forum by Microsoft's Ed Pinto:

Enabling cyclic references requires you to create a DataContractSerializer and passing true in for the preserveObjectReferences parameter.  You can control this by deriving from the DataContractSerializerOperationBehavior, overriding CreateSerializer and applying said behavior to operations where you want this to happen.  Sowmy's got a great blog post on this including sample code: http://blogs.msdn.com/sowmy/archive/2006/03/26/561188.aspx.

Please be aware that there is no interop story for the preservation of object references.

The rumor is that Microsoft deliberately made it difficult to set this attribute value to discourage non-interoperable bidirectional serialization scenarios. Bidirectional serialization injects id and idref attributes into the message that don't appear in the schema.

Note: Rick points to Christian Weyer's workaround to generate unsegmented WSDL documents with WCF in his Improving WCF Interoperability: Flattening your WSDL post of May 10, 2007.

2 comments:

Anonymous said...

A bit late this. But if anyone are using linqtosql and have this problem you can simply just open the tables in your dbml class. Right click next to a table and click properties.
HEre there is a property named Serialization Mode.. Set it to Unidirectional

The error will be gone

Anonymous said...

A bit late this. But if anyone are using linqtosql and have this problem you can simply just open the tables in your dbml class. Right click next to a table and click properties.
HEre there is a property named Serialization Mode.. Set it to Unidirectional

The error will be gone