// // Source : http://chabster.blogspot.com/2008/02/wcf-cyclic-references-support.html // With some modifications using System; using System.ServiceModel.Description; using System.Web.Services.Description; namespace Utils { [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Method)] public class CyclicReferencesAwareAttribute : Attribute, IContractBehavior, IOperationBehavior, IWsdlExportExtension { private readonly bool on = true; private ContractDescription contractDescription; private OperationDescription operationDescription; public CyclicReferencesAwareAttribute(bool on) { this.on = on; } public CyclicReferencesAwareAttribute() { on = true; } 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) { this.operationDescription = operationDescription; 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) { this.contractDescription = contractDescription; CyclicReferencesAwareContractBehavior.ReplaceDataContractSerializerOperationBehaviors(contractDescription, On); } void IContractBehavior.Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) { } #endregion /// /// When the contract is exported, we add "CyclicReferencesAwareAttribute" to the export so that the WSDL importer knows /// where to add the attribute on the client side. Yes, I'll admit it's a little kludge, but it seems to work. /// /// /// public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) { if (contractDescription != null) { context.WsdlPortType.Documentation = "CyclicReferencesAwareAttribute"; } else { Operation operation = context.GetOperation(operationDescription); if (operation != null) { operation.Documentation = "CyclicReferencesAwareAttribute"; } } } public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) { } } }