WCF cyclic references support
Object graph for type 'X.Y.Z' contains cycles and cannot be serialized if reference tracking is disablederror - read to the end.
There is a simple solution and it's well documented in the Preserving Object Reference in WCF article. However the code is very chaotic and contains mistakes. I've made several classes to support a simple and powerful control over the DataContract serialization parameters.
Support classes
-
ApplyCyclicDataContractSerializerOperationBehavior
An operation behavior and The
DataContractSerializerOperationBehavior
descendant. Used to inject custom configuredDataContractSerializer
instances into WCF pipeline.internal class ApplyCyclicDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior{ private readonly Int32 _maxItemsInObjectGraph; private readonly bool _ignoreExtensionDataObject; private readonly bool _preserveObjectReferences; public ApplyCyclicDataContractSerializerOperationBehavior(OperationDescription operationDescription, Int32 maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool preserveObjectReferences) : base(operationDescription) { _maxItemsInObjectGraph = maxItemsInObjectGraph; _ignoreExtensionDataObject = ignoreExtensionDataObject; _preserveObjectReferences = preserveObjectReferences; } public override XmlObjectSerializer CreateSerializer(Type type, String name, String ns, IList<Type> knownTypes) { return (new DataContractSerializer(type, name, ns, knownTypes, _maxItemsInObjectGraph, _ignoreExtensionDataObject, _preserveObjectReferences, null /*dataContractSurrogate*/)); } public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList<Type> knownTypes) { return (new DataContractSerializer(type, name, ns, knownTypes, _maxItemsInObjectGraph, _ignoreExtensionDataObject, _preserveObjectReferences, null /*dataContractSurrogate*/)); } }
-
CyclicReferencesAwareContractBehavior
A contract behavior. Used to apply the
DataContractSerializerOperationBehavior
operation behavior to every operation within a contract.public class CyclicReferencesAwareContractBehavior : IContractBehavior{ private const Int32 maxItemsInObjectGraph = 0xFFFF; private const bool ignoreExtensionDataObject = false; private bool _on; public CyclicReferencesAwareContractBehavior(bool on) { _on = on; } #region IContractBehavior Members public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) { ReplaceDataContractSerializerOperationBehaviors(contractDescription, _on); } public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) { ReplaceDataContractSerializerOperationBehaviors(contractDescription, _on); } internal static void ReplaceDataContractSerializerOperationBehaviors(ContractDescription contractDescription, bool on) { foreach (var operation in contractDescription.Operations) { ReplaceDataContractSerializerOperationBehavior(operation, on); } } internal static void ReplaceDataContractSerializerOperationBehavior(OperationDescription operation, bool on) { if (operation.Behaviors.Remove(typeof(DataContractSerializerOperationBehavior)) || operation.Behaviors.Remove(typeof(ApplyCyclicDataContractSerializerOperationBehavior))) { operation.Behaviors.Add(new ApplyCyclicDataContractSerializerOperationBehavior(operation, maxItemsInObjectGraph, ignoreExtensionDataObject, on)); } } public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } #endregion }
-
CyclicReferencesAwareAttribute
The most valuable member of the triade. Used to apply cycling support policy to the whole service interface or an individual interface operation.
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method)] public class CyclicReferencesAwareAttribute : Attribute, IContractBehavior, IOperationBehavior{ private readonly bool _on = true; public CyclicReferencesAwareAttribute(bool on) { _on = on; } public bool On { get { return (_on); } } #region IOperationBehavior Members void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation) { CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehavior(operationDescription, On); } void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation) { CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehavior(operationDescription, On); } void IOperationBehavior.Validate(OperationDescription operationDescription) { } #endregion #region IContractBehavior Members void IContractBehavior.AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { } void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) { CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehaviors(contractDescription, On); } void IContractBehavior.ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatchRuntime) { CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehaviors(contractDescription, On); } void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } #endregion }
Examples:
CyclicReferencesAware
applied to the whole interface:
[ServiceContract] [CyclicReferencesAware(true)] public interface TestFacade { [OperationContract] void Hello(SomeData data); }
CyclicReferencesAware
applied to individual operation(s):
[ServiceContract] public interface TestFacade { [OperationContract] [CyclicReferencesAware(true)] void Hello(SomeData data); }
CyclicReferencesAware
applied to the whole interface and individual operation(s):
[ServiceContract] [CyclicReferencesAware(false)] public interface TestFacade { [OperationContract] [CyclicReferencesAware(true)] void Hello(SomeData data); }
25 коммент.:
Works nicely, but what to do when sending the objects from client back to Server?
You must apply this attribute to the client interfaces as well.
Thanks for the nice article.
I assume that this attribute will need to be added to the service proxy either generated or coded manually? I'm using svcutil.exe to generate the proxies - there appears to be a mechanism to support the custom attribute:
http://msdn.microsoft.com/en-us/library/aa717040(VS.85).aspx
Sweet, works like a charm!
Great Article! I am wondering how or where I can apply this attribute to the client interface. thanks!
For anyone coming across this like I did. With the new .NET 3.5 SP1 you no longer need to pass an instance of DataContractSerializer to the WCF runtime and write the above. Simply specify the DataContract IsRefence to true.
[DataContract(IsReference = true)]
See an article here: http://www.zamd.net/2008/05/20/DataContractSerializerAndIsReferenceProperty.aspx
I.e.
[DataContract(IsReference = true)]
public class Employee
{
[DataMember]
public string Name { get; set; }
[DataMember]
public Employee Manager { get; set; }
}
Hey chabster and all u guys.
Was anybody able to send object from Silverlight back to server? It seems the classes u r using here don't exist in Silverlight.
Any idea? Thanks in advance
Thanks!
Works perfectly with EF POCO objects serialized over WCF web services!
R
Hi, great code! Is there a way to do this breadth first? I noticed that if I return this in a SOAP response the first object has the information as expected. However, then when it drills down to the type that cyclically references the first type, it populates the objects there. So on the top level I end up with 1 full object and a bunch of references. Ideally, I would like to have all the main data at the top level and the references when you drill down.
Thanks,
Hi! Could we use [CyclicReferencesAware(true)] with WCF RIA Services in some way?
Thanks!!!
Informative article, just what I needed.
Look at my homepage ; GFI Norte
Very descriptive post, I liked that a lot. Will there be a part 2?
Take a look at my web blog :: online backup services
Here is my blog post ... online backup solution
I seldom leave comments, however I read a ton of remarks
on "WCF cyclic references support". I do have a couple of questions for
you if you do not mind. Could it be simply me or do a few of these comments appear like
they are left by brain dead individuals? :-P And, if you are posting on
additional online social sites, I'd like to follow you. Would you list of every one of your shared sites like your linkedin profile, Facebook page or twitter feed?
My blog post :: online backup reviews
My homepage ... online backup server
I'm impressed, I have to admit. Seldom do I come across a blog that's
both equally educative and amusing, and let me tell you, you have hit the nail on
the head. The problem is something too few men and women are speaking intelligently about.
I am very happy that I came across this during
my hunt for something concerning this.
Review my weblog online backup
my site - online backup service
This info is invaluable. How can I find out more?
my blog ... insomnia lyrics 007
Here is my site : insomnia 5dpo
Hi, I would like to subscribe for this webpage to obtain most recent updates, so where can i do it please assist.
Also visit my site - insomnia movie
Here is my site : insomnia uiuc
We are a group of volunteers and opening a new scheme in our community.
Your website offered us with valuable info to work on.
You've done an impressive job and our entire community will be grateful to you.
Here is my weblog :: online backup free
Feel free to visit my web site online backup service
I know this if off topic but I'm looking into starting my own weblog and was wondering what all is needed to get set up? I'm
assuming having a blog like yours would cost
a pretty penny? I'm not very web savvy so I'm not 100% positive. Any tips or advice would be greatly appreciated. Thank you
Feel free to surf to my site insomnia facts
Feel free to surf my site : insomnia quote fight club
I'll right away grab your rss as I can not in finding your e-mail subscription hyperlink or e-newsletter service. Do you have any? Please let me realize in order that I could subscribe. Thanks.
My web blog ... diets that work for women
Thank you, I have recently been looking for info about this subject for a while and yours is the greatest I have
came upon till now. However, what concerning the conclusion?
Are you certain concerning the source?
my blog ... psn code
hello!,Ӏ love youг wrіting so
a lot! share we κeеp in tοuсh extгa
аbout уοur post on ΑОL?
I rеquіre a specialiѕt in thiѕ housе to гesοlvе mу problеm.
Maybe that's you! Looking ahead to see you.
Look at my webpage ... it support
Hi! I could have sworn I've been to this site before but after browsing through some of the post I realized it's
new to me. Anyways, I'm definitely delighted I found it and I'll be bookmarking and checking back often!
my webpage - home cellulite treatment
Wow that was strange. I just wrote an incredibly long comment but after I clicked submit my comment didn't show up. Grrrr... well I'm not writing all
that over again. Anyhow, just wanted to say great blog!
Here is my web page :: loggedonuser ()
Link exchange is nothing else except it is simply placing the other person's blog link on your page at suitable place and other person will also do similar in support of you.
Also visit my web page ... Adf.ly Earnings Booster
My relatives all the time say that I am wasting my
time here at web, however I know I am getting experience everyday
by reading such pleasant posts.
Also visit my weblog :: way to buy real cheap twitter followers free
Отправить комментарий