//
// 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)
{
}
}
}