For developers: Serialization with DataContractSerializer
Windows Communication Foundation uses DataContractSerializer for the serialization and deserialization of the messages. While the topic of the serialization in WCF is beyond the scope of this article, we will give some quick start instructions as well as point some common problems that accompany serialization.
The DataContract attribute
With the DataContractSerializer you are able to serialize objects in XML or JSON format, which is then transmitted to the client of the web service. There are two basic approaches to achieve this:
- You can simply return an instance of an object and WCF will serialize the object for you in XML or JSON, depending on the specified WebMessageFormat
- You can decorate the type that you will serialize with DataContract attribute and all the members that you wish to serialize with DataMember attribute
While the first approach is simpler, it has some serious drawbacks and second approach is highly recommended.
When preparing types for serialization (placing DataContract and DataMember attributes), you should have following in mind:
- Only public members can be serialized when working under medium trust environment. Since Sitefinity CMS does support medium trust environment, you should never mark non-public member with a DataMember attribute.
- For properties, both getter and setter must be defined and they both have to be public for serialization to work under medium trust environment.
- Not all types are serializable. For the list of supported types consult following resources: Types Supported by the Data Contract Serializer
- You can serialize only the instances of types decorated by the DataContract attribute. For any derived types that may be serialized, you need to decorate the type with the KnownTypes attribute and specify the derived type.
Example 1: Preparing a class for serialization
[DataContract]
public
class
Product
{
[DataMember]
public
Guid Id {
get
;
set
; }
public
Guid WarehouseId {
get
;
set
; }
[DataMember]
public
string
Name {
get
;
set
; }
[DataMember]
public
double
Price {
get
;
set
; }
}
In the example above, we have marked the Product class as DataContract and marked Id, Name and Price properties as DataMembers. Notice how we did not mark WarehouseId as a DataMember, because we do not wish to serialize this information via our web service.
Example 2: Preparing derived class for serialization
Often we will want to have our service to work with base class, while the actual instances served by the service will be derivations of such web service.
Consider following service and two data types.
public
class
ProductsService : IProducts
{
public
Product GetProduct()
{
return
new
Book();
}
}
[DataContract]
[KnownType(
typeof
(Book))]
public
class
Product
{
[DataMember]
public
Guid Id {
get
;
set
; }
public
Guid WarehouseId {
get
;
set
; }
[DataMember]
public
string
Name {
get
;
set
; }
[DataMember]
public
double
Price {
get
;
set
; }
}
public
class
Book : Product
{
}
Notice, how in the service we have a method GetProduct which returns an object of type Product, yet we are returning an instance of Book type (which is perfectly valid, since Book type is deriving from Product type). However, in order for this scenario to work, we need to decorate the Product class with the KnownType attribute and set the type of Book as a known type for that DataContract.