Search code examples
wcfdatacontractserializer

Do WCF and DataContractSerializer serialize CollectionDataContract-decorated collection types differently?


I have a really simple customized collection type that inherits from List<> and uses a CollectionDataContract.

When I use DataContractSerializer.WriteObject to serialize it, it respects the CollectionDataContract attribute the way I'd expect; however, when I use it as a return type for a WCF method, I get the default ArrayOfFoo.

I'm wondering if there is some decoration I'm missing in the service contract.

Details:

[DataContract(Namespace = "")]
public class Foo
{
    [DataMember]
    public string BarString { get; set; }
}

[CollectionDataContract(Namespace = "")]
[Serializable]
public class FooList : List<Foo> {}

If I just instantiate a Foo and then use DataContractSerializer.WriteObject to serialize it, I get what you'd expect:

<FooList>
    <Foo>
        <BarString>myString1</BarString>
    </Foo>
</FooList>

However, if I have a service with a method like this...

[ServiceContract Name = "MyService"]
public interface IMyService
{
    [OperationContract, WebGet(UriTemplate = "foos/")]
    FooList GetAllFoos();
}

and then do a GET for http://www.someEndpoint.com/foos/, I get this:

<ArrayOfFoo>
    <Foo>
        <BarString>myString1</BarString>
    </Foo>
</ArrayOfFoo>

I've also tried specifying Name="MyFooListName" in the CollectionDataContract attribute. Same results: DataContractSerializer gets the memo; WCF doesn't.


Solution

  • Saeed sent me in the right direction: I inadvertently ended up with XmlSerializer, when I had been hoping for DataContractSerializer.

    I had ended up with XmlSerializer... well... by asking for it.

    In particular, I had decorated methods in my service with the XmlSerializerFormat like this:

    [ServiceContract Name = "MyService"] 
    public interface IMyService 
    { 
        //  ... other stuff ...
    
        [OperationContract, WebInvoke(UriTemplate = "foos/", Method = "POST")] 
        [XmlSerializerFormat]
        Foo PostAFoo(Foo yourNewFoo);
    } 
    

    I had done this in the hopes of forgiving member order in hand-rolled Foo XML blobs. Of course, when one does this one ends up with XmlSerializer, not DataContractSerializer.

    When I take away the XmlSerializerFormat attribute, problem solved: WCF is now serializing my FooList collection the way I want.