Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

WCF Support for xs:date

4.75/5 (4 votes)
17 Apr 2011CPOL4 min read 49.1K   759  
WCF interoperability with other frameworks when transferring date values

Introduction

Despite the fact that WCF technology is powerful and flexible, there are some areas requiring improvement. In this article, I'll show issues related to webservice date format interoperability and how it can be solved.

Background

My company is a financial institution which has many different applications exchanging data. Most of these applications are implemented in Java while mine exposes webservice implemented in WCF .NET.

To exchange dates, I’ve proposed an xs:dateTime format. This is because then I was not aware about the peculiarities of this type.

First issue: UTC format. When I was testing webservice with soapUI, I entered manually 1969-03-17T00:00:00.000+01:00 as an input argument for 1969-03-17 date of birth. Everything was fine. However when the actual webservice client sent 1969-03-16T23:00:00.000Z (equivalent datetime in UTC format), then it appeared that .NET treated this as 1969-03-16 date (one day shift).

One more explanation: I’m working in Poland, so the winter time is GMT+1 and summer time is GMT+2 CET zone with daylight savings time.

So it looks like UTC time is not correctly handled. Fortunately, a simple workaround exists:

C#
if (date.Kind == DateTimeKind.Utc) 
date = date.ToLocalTime()    

Second, more difficult issue is the following: For some date values, different frameworks have different representation. For example, my WCF webservice got 1941-12-05T00:00:00.000+02:00. Java client intent was to send 1941-12-05 date while .NET service treats this as a 1941-12-04. We’ve found that about 5% of dates had similar issue. Most of these dates were from 40s but not only. A possible explanation is that daylight saving time was not used in 40s. Or maybe one framework used Germany's daylight saving time for II WW period?

If you start thinking about the daylight time differences between frameworks, then the idea of representing dates in this way becomes just crazy. So frameworks have to remember historical dates of daylight time period? Do they take into account historical accidents like changing borders (and timezones)? Where is it documented? What to do if algorithms differ? What parameters have influence on TZ interpretation? We know that most important are regional setting on Windows. How about Linux, AIX? Do all servers have correct and compatible settings?

Ok, so xs:dateTime is not a good option because of differences between frameworks. What are the other alternatives? What about xs:string? Unfortunately, this is also not a good option: there are plenty of different formats in use: dd-MM-yyyy, yyyy-MM-dd, yyyyMMdd, … . In some scenarios, it is ok – for example one webservice for one client. For some, it is not sufficient: when webservices from multiple systems are reused on ServiceBus to create new webservice, then all must agree to one format. Sometimes however, the format can’t be changed because many clients are using it.

The best option would be to use xs:date without timezones (option available for xs:date). However in WCF, this is not supported. I’ve Googled much and haven’t found a satisfactory solution. Ok, I’ve found that one can force WCF to use XmlSerializer which is able to use xs:date. But I prefer to use DataContractSerializer because of other reasons. And most important: XmlSerializer will not handle xs:date for simple service parameters. XmlSerializer requirement is that date has to be a property of the object.

So what is my proposal? I found the following solution: custom-made xs:date. It’s not as complicated as it seems.

Using the Code

I’ve defined my own type – WcfDate which implements IXmlSerializable interface. It is enough to use that type instead of DateTime in .NET code in Service Contract.

For example:

C#
[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(WcfDate value);
    
    [OperationContract]
    CompositeType GetDataUsingDataContract(CompositeType composite);
}

[DataContract]
public class CompositeType
{
    bool boolValue = true;
    string stringValue = "Hello ";
    WcfDate dateValue = new WcfDate(DateTime.Today);
    
    [DataMember]
    public bool BoolValue
    {
        get { return boolValue; }
        set { boolValue = value; }
    }
    
    [DataMember]
    public string StringValue
    {
        get { return stringValue; }
        set { stringValue = value; }
    }
    
    [DataMember]
    public WcfDate DateValue
    {
        get { return dateValue; }
        set { dateValue = value; }
    }
}       

WcfDate is rendered as xs:date in soap envelop during runtime. I’ve also added some extension methods to make easy conversion between WcfDate and DateTime. For example, it is possible to increment incoming date in one line:

C#
composite.DateValue = composite.DateValue.GetDate().AddDays(1).ToWcfDate();    

All details are in the attached code: WcfCommon project provides WcfDate type and WsdlDocumentation attribute (copied from Microsoft samples) and WcfSampleService shows how to use WcfDate.

Shortcomings

xs:date is not supported on client side when you generate proxy. Element xs:date is treated then as xs:string. Client has to parse date by itself but still it is better than before because xs:date enforces standard date layout.

Further Conclusions

Date type is very useful. It exists in most databases including SQL Server and in many frameworks and languages (although not all). Our life would be easier if Microsoft supported it in WCF and in the .NET Framework natively.

History

  • 15th April, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)