5

I am not sure if it is an issue or not.

If I use List here, It works in both root/xml/metadata?op=Competitions and root/Competitions

[DataContract]
public class CompetitionsResponse : IHasResponseStatus
{
    [DataMember]

    public List<Competitions> Competitions { get; set; }

    //Auto inject and serialize web service exceptions
    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

HTTP/1.1 200 OK Content-Type: application/xml Content-Length: length

<CompetitionsResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FSI.API.ServiceModel">
  <Competitions>
    <Competitions>
      <CompName>String</CompName>
      <CompType>String</CompType>
      <CompetitionID>0</CompetitionID>
    </Competitions>
  </Competitions>
  <ResponseStatus xmlns:d2p1="http://schemas.servicestack.net/types">
    <d2p1:ErrorCode>String</d2p1:ErrorCode>
    <d2p1:Errors>
      <d2p1:ResponseError>
        <d2p1:ErrorCode>String</d2p1:ErrorCode>
        <d2p1:FieldName>String</d2p1:FieldName>
        <d2p1:Message>String</d2p1:Message>
      </d2p1:ResponseError>
    </d2p1:Errors>
    <d2p1:Message>String</d2p1:Message>
    <d2p1:StackTrace>String</d2p1:StackTrace>
  </ResponseStatus>
</CompetitionsResponse>

But if I use "IEnumerable"

[DataContract]
public class CompetitionsResponse : IHasResponseStatus
{
    [DataMember]
    public IEnumerable<Competitions> Competitions { get; set; }

    //Auto inject and serialize web service exceptions
    [DataMember]
    public ResponseStatus ResponseStatus { get; set; }
}

The Competitions collection disappeared from the meta page root/xml/metadata?op=Competitions

HTTP/1.1 200 OK

Content-Type: application/xml Content-Length: length

<CompetitionsResponse xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/FSI.API.ServiceModel">
  <Competitions i:nil="true" />
  <ResponseStatus xmlns:d2p1="http://schemas.servicestack.net/types">
    <d2p1:ErrorCode>String</d2p1:ErrorCode>
    <d2p1:Errors>
      <d2p1:ResponseError>
        <d2p1:ErrorCode>String</d2p1:ErrorCode>
        <d2p1:FieldName>String</d2p1:FieldName>
        <d2p1:Message>String</d2p1:Message>
      </d2p1:ResponseError>
    </d2p1:Errors>
    <d2p1:Message>String</d2p1:Message>
    <d2p1:StackTrace>String</d2p1:StackTrace>
  </ResponseStatus>
</CompetitionsResponse>
ValidfroM
  • 2,626
  • 3
  • 30
  • 41

1 Answers1

3

ServiceStack uses the .NET's XML DataContractSerializer under the hood for its XML Serialization which is the behavior your seeing. It also works with POCOs i.e. the [DataContract] and [DataMember] attributes are optional.

It's also not recommended to use interfaces on DTO's (IMO there's no good reason to) which should be as typed and as self-describing as possible. Many serializes won't know what the concrete type of the IEnumerable should be so has to do some hacks like output dynamic typeinfo metadata in the payload, or assume a default collection type.

Note: If you want the XML to be prettier than you should define a namespace for your DTOs - the best way to do that is define an Assembly Attribute in your AssemblyInfo.cs file:

[assembly: ContractNamespace("http://schemas.servicestack.net/types",  
    ClrNamespace = "FSI.API.ServiceModel")]
mythz
  • 141,670
  • 29
  • 246
  • 390
  • I realize this is pretty old, but still. Wouldn't IEnumerable be the one interface you want to use when serializing? It would allow to yield return the collection. When reading from the database and streaming to the network this could be a useful optimization. – AVee Jun 17 '15 at 08:55