msi
msi

Reputation: 3212

WCF Custom serialization based on params

Can I implement some custom serialization (SOAP) to serialize only the fields which can be changed dynamically?

Class:

[DataContract]
public class Video
{
    ...

    [DataMember]
    public int Width { get; set; }

    [DataMember]
    public int Height { get; set; }

    [DataMember]
    public short Bitrate { get; set; }

    [DataMember]
    public short Framerate { get; set; }

    [DataMember]
    public long Duration { get; set; }

    [DataMember(EmitDefaultValue = false)]
    public VideoType Type { get; set; }
}

WCF Method:

public Video GetPartVideo(params string[] fields)
{
    var video = new Video
    {
        Name = "Test Video",
        Description = "Description of the Test Video",
        CreatedAt = DateTime.Now,
        ModifiedAt = DateTime.Now,
        Url = "",
        FileName = "",
        FileSize = 100,
        Width = 640,
        Height = 480,
        Bitrate = 120,
        Framerate = 32,
        Duration = 100200300,
        Type = VideoType.StandardDefinition
    };

    return video;
} 

Method call:

<GetPartVideo>
  <MethodParameters>
    <fields attr0="StringArray" isNull="false">
      <StringArray0>Name</StringArray0>
      <StringArray1>Description</StringArray1>
    </fields>
  </MethodParameters>
</GetPartVideo>

SOAP Response (simplified):

<GetPartVideo>
  <MethodParameters>
    <Video>
      <Description>Description of the Test Video</Description>
      <Name>Test Video</Name>
    </Video>
  </MethodParameters>
</GetPartVideo>

Upvotes: 1

Views: 1840

Answers (1)

msi
msi

Reputation: 3212

I have found the response by myself.

It is possible to use Serializer Format Attribute, to change serialization

public class CustomDataContractSerializerOperationBehavior : DataContractSerializerOperationBehavior
{
    public CustomDataContractSerializerOperationBehavior(OperationDescription operationDescription) : base(operationDescription) { }

    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList<Type> knownTypes)
    {
        var dictionary = new XmlDictionary(2);
        dictionary.Add(name);
        dictionary.Add(ns);


        return new MyCustomDataContractSerializer(
            type,
            new XmlDictionaryString(dictionary, name, 0),
            new XmlDictionaryString(dictionary, ns, 1), 
            knownTypes);
    }

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


public class CustomDataContractFormatAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void ApplyDispatchBehavior(OperationDescription description, DispatchOperation dispatch)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }

    public void Validate(OperationDescription description)
    {
    }

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

        if (dcs != null)
            description.Behaviors.Remove(dcs);

        description.Behaviors.Add(new CustomDataContractSerializerOperationBehavior(description));
    }
}

also the class MyCustomDataContractSerializer should override the XmlObjectSerializer

and Service can be decorated with the custom format attributes

[ServiceContract(Namespace = "http://tesmpuri.com/")]
[ServiceKnownType(typeof(Video))]
public interface IPartialResponseTestService
{
    [OperationContract]
    Video GetFullVideo();

    [OperationContract]
    [CustomDataContractFormat]
    Video GetPartVideo(params string[] fields);

    [OperationContract]
    [XmlSerializerFormat]
    Video GetVideo();
}

Upvotes: 2

Related Questions