I am currently changing part of our infrastructure to WCF and stumbled upon this unanswered question and decided to give it a try. :)
The way WCF DateTime
and DateTimeOffset
are serialized seems a bit odd. As the following example shows, using DateTime
looks like the best option when working with other platforms:
using System; using System.Runtime.Serialization; using System.ServiceModel; [ServiceContract] public class DateTimeOffsetService { [OperationContract] public Container DoWork() { return new Container { NowDateTime = DateTime.Now, UtcNowDateTime = DateTime.UtcNow, NowDateTimeOffset = DateTimeOffset.Now, UtcNowDateTimeOffset = DateTimeOffset.UtcNow }; } } [DataContract] public class Container { [DataMember] public DateTime NowDateTime { get; set; } [DataMember] public DateTime UtcNowDateTime { get; set; } [DataMember] public DateTimeOffset NowDateTimeOffset { get; set; } [DataMember] public DateTimeOffset UtcNowDateTimeOffset { get; set; } }
XML response request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Header /> <s:Body> <DoWorkResponse xmlns="http://tempuri.org/"> <DoWorkResult xmlns:a="http://schemas.datacontract.org/2004/07/RD.MES.WcfService" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <a:NowDateTime>2012-03-23T15:59:47.8328698+01:00</a:NowDateTime> <a:NowDateTimeOffset xmlns:b="http://schemas.datacontract.org/2004/07/System"> <b:DateTime>2012-03-23T14:59:47.8328698Z</b:DateTime> <b:OffsetMinutes>60</b:OffsetMinutes> </a:NowDateTimeOffset> <a:UtcNowDateTime>2012-03-23T14:59:47.8328698Z</a:UtcNowDateTime> <a:UtcNowDateTimeOffset xmlns:b="http://schemas.datacontract.org/2004/07/System"> <b:DateTime>2012-03-23T14:59:47.8328698Z</b:DateTime> <b:OffsetMinutes>0</b:OffsetMinutes> </a:UtcNowDateTimeOffset> </DoWorkResult> </DoWorkResponse> </s:Body> </s:Envelope>
I am in the GMT + 01.00 time zone, so the values seem to be correct. Why is that? Well, WSDL defines a Container
as follows:
<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/WcfService"> <xs:import schemaLocation="http://localhost:3608/DateTimeOffsetService.svc?xsd=xsd3" namespace="http://schemas.datacontract.org/2004/07/System"/> <xs:complexType name="Container"> <xs:sequence> <xs:element minOccurs="0" name="NowDateTime" type="xs:dateTime"/> <xs:element minOccurs="0" name="NowDateTimeOffset" type="q1:DateTimeOffset"/> <xs:element minOccurs="0" name="UtcNowDateTime" type="xs:dateTime"/> <xs:element minOccurs="0" name="UtcNowDateTimeOffset" type="q2:DateTimeOffset"/> </xs:sequence> </xs:complexType> <xs:element name="Container" nillable="true" type="tns:Container"/> </xs:schema>
And DateTimeOffset
- in WSDL - is defined as:
<xs:schema elementFormDefault="qualified" targetNamespace="http://schemas.datacontract.org/2004/07/System"> <xs:import schemaLocation="http://localhost:3608/DateTimeOffsetService.svc?xsd=xsd1" namespace="http://schemas.microsoft.com/2003/10/Serialization/"/> <xs:complexType name="DateTimeOffset"> <xs:annotation> <xs:appinfo> <IsValueType>true</IsValueType> </xs:appinfo> </xs:annotation> <xs:sequence> <xs:element name="DateTime" type="xs:dateTime"/> <xs:element name="OffsetMinutes" type="xs:short"/> </xs:sequence> </xs:complexType> <xs:element name="DateTimeOffset" nillable="true" type="tns:DateTimeOffset"/> </xs:schema>
Basically, DateTime
serialized as the standard xs:dateTime
(which has the right timezone component), and DateTimeOffset
serialized into a non-standard complex type that the caller would need to correctly understand and process.
FWIW; Since I found this, I will probably use DateTime
for the WCF interface if I really don't need to care about different timezone offsets.
Currently, the only excuse I could see for using a complex type (since xs:dateTime
should contain all the information it does!) Is that if xs:dateTime
used to serialize DateTime
and DateTimeOffset
, the WCF client I wouldn’t know which type to use.