3

Given a (contrived) base class, and a sub class we want to serialize via WCF using the XmlSerializer. We decorate a collection (see the response class) as per the article:

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlelementattribute.aspx (see remarks section).

Issue is that although the correct WSDL seems to be generated, SVCUtil generates a class file where the GetUserResponse class contains a property named Items. Is this to do with applying [XmlElement] to an array? Although the XmlArray element doesn't have a Type property.

Thanks in advance.

[Serializable]
[XmlType]
public class UserBase
{
    public int Id {get;set;}
}

[Serializable]
[XmlType]
public class BasicUser : UserBase
{
    public string UserName {get;set;}
}

[Serializable]
[XmlType]
public class SuperUser : UserBase
{
    public string UserName {get;set;}
    public bool SpecialLevel {get;set;}

}

[Serializable]
[XmlType]
public class GetUserResponse
{
    [XmlElement("Users", typeof(User)), XmlElement("SuperUsers", typeof(SuperUser))]
    public List<UserBase> Users {get;set;}
}
6footunder
  • 1,318
  • 18
  • 29
  • Why do you need to use the XmlSerializer? Why not just use the Data Contract Serializer, which is faster and more flexible? – John Saunders Nov 23 '10 at 20:12
  • btw, `[Serializable]` doesn't add anything here, unless you are also using `BinaryFormatter` somewhere. – Marc Gravell Nov 23 '10 at 20:15
  • @John - Thanks mate - we've only experienced 100000000 hours of needless aggravation from the XmlSerializer. It's not being used by choice. There are interop concerns (i.e DataContractSerializer is actually *less* flexible in the places we need). – 6footunder Nov 23 '10 at 20:40

1 Answers1

7

Because you are using [XmlElement] on the collection property, the corresponding xml is going to be something like:

<GetUserResponse>
    <Users>{this is a user}</Users>
    <Users>{this is a user}</Users>
    <SuperUsers>{this is a super user}</SuperUsers>
    <Users>{this is a user}</Users>
    <SuperUsers>{this is a super user}</SuperUsers>
</GetUserResponse>

there isn't really anywhere it can get a better name for a collection property, other than Items. I wonder if it might be better to use:

[XmlArray("Users")]
[XmlArrayItem("User", typeof(User))]
[XmlArrayItem("SuperUser", typeof(SuperUser))]

in order to build:

<GetUserResponse>
    <Users>
        <User>{this is a user}</User>
        <User>{this is a user}</User>
        <SuperUser>{this is a super user}</SuperUser>
        <User>{this is a user}</User>
        <SuperUser>{this is a super user}</SuperUser>
    </Users>
</GetUserResponse>

then you would have a Users property.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • OMG. Why did I not see the XmlArray ctor had a typeof override???? I'll quickly test this and then mark this answer up. Thanks Marc. – 6footunder Nov 23 '10 at 20:44