views:

342

answers:

3

I have some simple POCO object:

public class ProductCategoryDTO
{
        public string Name { get; set; }
        public DateTime ModifiedDate { get; set; }
}

As sometimes field order is important (for example, if sending to Infopath forms), I need to keep element order when serializing.

And now I am confused, what attributes I should use for the class and for each field. I know that:

  • DataContractSerializer uses [DataContract] and [DataMember(Order = n)]
  • XMLSerializer uses [Serializable] and [XmlElementAttribute(Order = n)].

Then what attributes to use if I want to support both XMLSerializer and DataContractSerializer, so it can used in both WCF or ASP. web services?

A: 

Order of XML elements should be dictated by the WSDL and you don't need to worry about it. Starting from .NET 3.5 SP1 you no longer need to use DataContractAttribute and DataMemberAttribute. The serializer will automatically include all public properties. As far as XmlSerializer is concerned, the SerializableAttribute has no effect. This attribute is used for binary serialization by the BinaryFormatter. So to resume, you could leave the class as a POCO, expose it either in WCF or ASP.NET webservice and leave the clients consume it according to the WSDL.

Darin Dimitrov
I refer to this one:http://stackoverflow.com/questions/612160/any-way-to-make-xmlserializer-output-xml-in-a-defined-orderand there was also a topic about Adobe/flex developers - they complained that for .NET web methods the order of fields changes almost each time the class library or web service is rebuilt. Also I had a bad experience with Infopath forms - they expect to receive elements in some certain order. To avoid implementing our own solution, the easiest way was to put Order attribute or else our Infopath form developers went crazy adjusting xsl on every build :D
Martin
+1  A: 

I don't see any reason why you couldn't put both attributes on the class and member properties, if you really must. Doesn't look nice, but if it works for you, that's just fine!

[DataContract(Namespace="....")]
[XmlType]
public class ProductCategoryDTO
{
        [DataMember(Order=1)]
        [XmlElementAttribute(Order=1)]
        public string Name { get; set; }

        [DataMember(Order=2)]
        [XmlElementAttribute(Order=2)]
        public DateTime ModifiedDate { get; set; }
}
marc_s
Yes, I had this on my mind too. I just hoped that maybe DataContract can use also [XmlElementAttribute(Order=n)]
Martin
@Martin: no those two serializer are totally separate and totally different and don't use each other's attributes.
marc_s
You probably mean XmlType on the `class`, btw.
Marc Gravell
@MArcG: yes, of course :-)
marc_s
+3  A: 

Strictly speaking, you don't need to use any attributes for either ;-p It used to be that DataContractSerializer would demand [DataContract] / [DataMember] (and they absolutely should be used), but you can use it without (but it then acts in a very dubious way similar to BinaryFormatter). Likewise, XmlSerializer doesn't need anything unless you want to control things. There are, however, some differences you should note:

  • XmlSerializer demands (and uses) a public parameterless constructor; DataContractSerializer doesn't use a constructor (at all). So watch out for that, and don't (for WCF) rely on code in the ctor - if you have necessary init code, use a serialization callback for WCF.
  • XmlSerializer demands either public fields (yeuch) or public properties with both get and set (even for lists); DataContractSerializer will happily work against private members, properties with (for example) a public get and private set, and collections without a `set (as long as your type initialises it).
  • XmlSerializer demands public types; IIRC DataContractSerializer is less fussy

So yes; you can support both serializers, and you can add any number of attributes in parallel, but note the above if you want total compatibility.

Another option is to just use XmlSerializer; you can configure WCF to use XmlSerializer by using [XmlSerialzerFormat]. Both options support inheritance, via [XmlInclude] and [KnownType].

Finally, note that if you implement IXmlSerializable, this takes precedence over either, but it hard to get right. Don't do that unless you have to.

Marc Gravell