There is a parameter in DataContractSerializer constructor that can be set to true to preserve the object references.
I found two ways to fix that issue:
1- using [DataContract(IsReference = true)] attribute on the entity
1 2 3 4 5 6 7 8 9 | [DataContract(IsReference = true )] public class Customer { [DataMember] public string Name { get ; set ; } [DataMember] public Order Order { get ; set ; } } |
2- using custom attribute on service operations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Channels; using System.ServiceModel.Dispatcher; using System.Runtime.Serialization; namespace MyWcfService { [Serializable] public class DataContractSerializerCircularReferenceFixAttribute : Attribute, IOperationBehavior { private readonly DataContractSerializerCircularReferenceFixOperationBehavior _innerOperationBehavior; public DataContractSerializerCircularReferenceFixAttribute() { } public DataContractSerializerCircularReferenceFixAttribute(OperationDescription operation) { _innerOperationBehavior = new DataContractSerializerCircularReferenceFixOperationBehavior(operation); } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { if (_innerOperationBehavior == null ) return ; (_innerOperationBehavior as IOperationBehavior).AddBindingParameters(operationDescription, bindingParameters); } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { ReplaceDataContractSerializerOperationBehavior(operationDescription); } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { ReplaceDataContractSerializerOperationBehavior(operationDescription); } public void Validate(OperationDescription operationDescription) { if (_innerOperationBehavior == null ) return ; (_innerOperationBehavior as IOperationBehavior).Validate(operationDescription); } private void ReplaceDataContractSerializerOperationBehavior(OperationDescription description) { var operationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>(); if (operationBehavior == null ) return ; description.Behaviors.Remove(operationBehavior); description.Behaviors.Add( new DataContractSerializerCircularReferenceFixOperationBehavior(description)); } } class DataContractSerializerCircularReferenceFixOperationBehavior : DataContractSerializerOperationBehavior { public DataContractSerializerCircularReferenceFixOperationBehavior(OperationDescription operation) : base (operation) { } public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes) { return new DataContractSerializer(type, name, ns, knownTypes, this .MaxItemsInObjectGraph, this .IgnoreExtensionDataObject, true , this .DataContractSurrogate); } public override XmlObjectSerializer CreateSerializer(Type type, System.Xml.XmlDictionaryString name, System.Xml.XmlDictionaryString ns, IList<Type> knownTypes) { return new DataContractSerializer(type, name, ns, knownTypes, this .MaxItemsInObjectGraph, this .IgnoreExtensionDataObject, true , this .DataContractSurrogate); } } } // WCF Service-------------------------------------- [ServiceContract] public class MyService { [OperationContract] [DataContractSerializerCircularReferenceFix] public Customer GetCustomer( string id){ //code here } } |