Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webservice - How to pass timezone info in a datetime element

I've been given a wsdl and I have to create a web service following its specs; I'm using visual studio 2010. Among the others there is also the definition of this complex type:

    <xsd:complexType name="Person">
        <xsd:sequence>
            <xsd:element name="surname" type="xsd:string"/>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="birthDate" nillable="true" type="xsd:dateTime"/>
        </xsd:sequence>
    </xsd:complexType>

Using VS I got the following cs (I don't recall exaclty how I did but I followed instructions found on the web):

    /// <remarks/>
    [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "4.0.30319.1")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://XXX/Submitter/")]
    public partial class Person {
        private string surnameField;
        private string nameField;
        private System.Nullable<System.DateTime> birthDateField;

        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string surname {
            get {
                return this.surnameField;
            }
            set {
                this.surnameField = value;
            }
        }
        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
        public string name {
            get {
                return this.nameField;
            }
            set {
                this.nameField = value;
            }
        }
        /// <remarks/>
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, IsNullable=true)]
        public System.Nullable<System.DateTime> birthDate {
            get {
                return this.birthDateField;
            }
            set {
                this.birthDateField = value;
            }
        }

And everything is correct: it compiles, runs and gives expected result; the only problem is that the other party that gave me the wsdl, when calling my web service, expects to get the birthdate field as

2013-02-15T17:28:00+01:00

with the time zone information, while the result they receive is like

2015-11-17T18:30:11

without timezone.

My problem is that I have a DateTime? type and that is the one I pass to my object instantiated from the class; should I override the serialization or there is another most common solution? Thanks

like image 876
Simone Avatar asked Oct 19 '22 21:10

Simone


1 Answers

Unfortunately, there's a significant mismatch between XSD and what .NET supports in SOAP web services.

.NET only has two types for this sort of information - DateTime and DateTimeOffset. Technically, it would be best if xs:datetime mapped to DateTimeOffset, but that's not how it works. Instead xs:datetime is mapped to DateTime, and relies heavily on the Kind property of the value to determine how it's serialized.

  • When the DateTime.Kind is DateTimeKind.Unspecified, no offset information is passed.

  • When the DateTime.Kind is DateTimeKind.Utc, then Z is passed, which is the same as +00:00.

  • When the DateTime.Kind is DateTimeKind.Local, then the local offset corresponding to the given date is passed.

You can apply a kind by using DateTime.SpecifyKind, or if you want to convert the value in the process, you can use .ToUniversalTime() or .ToLocalTime(). Or, if you know the values belong to a specific time zone, you can use the conversion methods from the TimeZoneInfo object. As long as the resulting kind is anything other than Unspecified it will include an offset.

Unfortunately, there is no option to specify an arbitrary offset. That would require the DateTimeOffset type, which isn't supported in SOAP services.

Also, consider that really the xs:datetime type is the wrong type for a birth date. It should be using xs:date, which is just a date, such as "2013-02-15". There's currently no type that supports this in .NET, though there is one coming soon, as Date in the System.Time package in corefxlab package. This will be useful for scenarios like these, but it remains to be seen if we can go back and fix the SOAP serializers to use them.

Really, the best idea is to not use XML and SOAP. Design your web services around JSON and REST instead. There you can have full control over things like this.

like image 59
Matt Johnson-Pint Avatar answered Oct 21 '22 15:10

Matt Johnson-Pint