Dat­a­Con­tract­Se­ri­al­izer

For those of your who are famil­iar with WCF you would no doubt know about the Dat­a­Con­tract­Se­ri­al­izer class, the Dat­a­Con­tract­Se­ri­al­izer does not include the CLR type infor­ma­tion in the seri­al­ized XML, which allows for loose cou­pling between the client and server because they don’t have to share the same CLR types.

How­ever, this also means you often have to re-create the same types on the client, though Visual Stu­dio han­dles most of this for you when you add a new ser­vice ref­er­ence to your project. How­ever, rather than dese­ri­al­iz­ing the orig­i­nal type, mes­sages are dese­ri­al­ized into a new, but iden­ti­cal CLR type on the client.

Net­Dat­a­Con­tract­Se­ri­al­izer

Whilst Dat­a­Con­tract­Se­ri­al­izer is used by WCF by default, there is another seri­al­izer which you can use if you wish to share the same CLR types between the client and server – the Net­Dat­a­Con­tract­Se­ri­al­izer. The Net­Dat­a­Con­tract­Se­ri­al­izer dif­fers from the Dat­a­Con­tract­Se­ri­al­izer in that it includes the CLR type infor­ma­tion in the seri­al­ized XML and can only be used if the same CLR types are seri­al­ized and dese­ri­al­ized at both ends.

You can use the Net­Dat­a­Con­tract­Se­ri­al­izer on any type which are marked with the Dat­a­Con­trac­tAt­tribute or Seri­al­iz­ableAt­tribute, or types that imple­ment the ISe­ri­al­iz­able interface.

UseNet­Dat­a­Con­tract­Se­ri­al­iz­er­At­tribute

Here’s the attribute you need to replace the default Dat­a­Con­tract­Se­ri­al­izer with the Net­Dat­a­Con­tract­Se­ri­al­izer, taken from Tim Scott’s blog post here:

public class NetDataContractOperationBehavior : DataContractSerializerOperationBehavior
{
    public NetDataContractOperationBehavior(OperationDescription operation) : base(operation)
    {
    }

    public NetDataContractOperationBehavior(
                OperationDescription operation,
                DataContractFormatAttribute dataContractFormatAttribute)
            : base(operation, dataContractFormatAttribute)
    {
    }

    public override XmlObjectSerializer CreateSerializer(
                Type type, string name, string ns, IList<Type> knownTypes)
    {
        return new NetDataContractSerializer(name, ns);
    }

    public override XmlObjectSerializer CreateSerializer(
                Type type, XmlDictionaryString name, XmlDictionaryString ns,
                IList<Type> knownTypes)
    {
        return new NetDataContractSerializer(name, ns);
    }
}

public class UseNetDataContractSerializerAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description,
                                     BindingParameterCollection parameters)</pre>
    {
    }

    public void ApplyClientBehavior(OperationDescription description,
                                    System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void ApplyDispatchBehavior(OperationDescription description,
                                      System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void Validate(OperationDescription description)
    {
    }

    private static void ReplaceDataContractSerializerOperationBehavior(
                OperationDescription description)
    {
        DataContractSerializerOperationBehavior dcsOperationBehavior =
        description.Behaviors.Find<DataContractSerializerOperationBehavior>();

        if (dcsOperationBehavior != null)
        {
            description.Behaviors.Remove(dcsOperationBehavior);
            description.Behaviors.Add(new NetDataContractOperationBehavior(description));
        }
    }
}

To use it, you can add it to a ser­vice method defined in the contract:

[OperationContract]
[UseNetDataContractSerializer]
Company SaveCompany(CompanyUpdater companyUpdater);
Share