简体   繁体   中英

Using a DataContractSurrogate with WCF REST

How can I use a DataContractSurrogate for my WCF REST service (hosted using a WebServiceHostFactory)?

I don't see a way of adding one and even if I add a custom IOperationBehavior, the WebServiceHost automatically overwrites and ignores it.

You can achieve this with the following two steps:

First, implement IDatacontractSurrogate interface:

class MySurrogate : IDataContractSurrogate
{

    public Type GetDataContractType(Type type)
    {
        //Implementation here
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        //Implementation here
    }

    //Implemenentation of the remaining methods...
}

Second, set your surrogate on the ServiceHost like this:

foreach (var endpoint in serviceHost.Description.Endpoints)
{
    foreach (var operation in endpoint.Contract.Operations)
    {
         operation.Behaviors.Find<DataContractSerializerOperationBehavior>().DataContractSurrogate = new MySurrogate();
    }
}

Remember to do this before you open your service host. Otherwise it may not work.

In case you're using IIS hosting and specifying the WebServiceHostFactory in an .svc file, then understandably, you don't have the opportunity set the surrogate. To overcome that, you have two options:

  1. Create a custom service behavior attribute and set the surrogate in its ApplyDispatchBehavior() method. Once you place this attribute on your sevice, WCF will automatically execute this method and the surrogate will be set.

  2. Create your own custom service host by subclassing WebServiceHost . Then set the surrogate in its ApplyConfiguration() method. This too will have the same effect.

I managed to get it working: WCF 4.0 REST service hosted using a WebServiceHostFactory in IIS.

I used a custom attribute to inject my NHProxyDataContractSurrogate:

public class CanSerializeNHProxyAttribute : Attribute, IContractBehavior
{
    public void ApplyClientBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime proxy)
    {
        foreach (OperationDescription opDesc in description.Operations)
        {
            ApplyDataContractSurrogate(opDesc);
        }
    }

    public void ApplyDispatchBehavior(ContractDescription description, ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.DispatchRuntime dispatch)
    {
        foreach (OperationDescription opDesc in description.Operations)
        {
            ApplyDataContractSurrogate(opDesc);
        }
    }

    private static void ApplyDataContractSurrogate(OperationDescription description)
    {
        DataContractSerializerOperationBehavior dcsOperationBehavior = description.Behaviors.Find<DataContractSerializerOperationBehavior>();
        if (dcsOperationBehavior != null)
        {
            if (dcsOperationBehavior.DataContractSurrogate == null)
                dcsOperationBehavior.DataContractSurrogate = new NHProxyDataContractSurrogate();
        }
    }

    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint serviceEndPoint, BindingParameterCollection parameters) { }

    public void Validate(ContractDescription contractDescription, ServiceEndpoint serviceEndPoint) { }
}

And applied the custom attribute to my ServiceContract:

[ServiceContract]
[CanSerializeNHProxy]
public interface IElementManager
{ ... }

I got a lot of useful info from these links:

DataContractSurrogate MSDN page, pointing to custom attribute

DataContractSurrogate implementation for serializing NHibernate proxy objects

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM