2012-02-07 11 views
6

Tengo un servicio .NET WCF con unos pocos contratos de operación que toma un DateTimeOffset. La idea es evitar cualquier confusión con horario de verano y zonas horarias.WCF DateTimeOffset compatibilidad

Sin embargo, tengo dudas de que utilizar DateTimeOffset es una buena idea, ya que es bastante no estándar y causaría dolores de cabeza a cualquiera que intente conectarse con, por ejemplo, una aplicación Java o una aplicación .NET vinculada a un versión .NET anterior.

Una alternativa es esperar un UTC DateTime, pero esto introduce el riesgo de que alguien olvide utilizar la hora UTC y llame al servicio con una hora local. También podría esperar una hora local DateTime, ya que los clientes siempre estarán en la misma zona horaria, pero esto deja una ambigüedad sutil, pero clásica, en torno a los cambios de horario de verano.

¿Alguien tiene historias de dolor de cabeza con DateTimeOffset en una interfaz de servicio o es relativamente fácil de usar después de todo?

+0

Como un lado - DateTimeOffset está de hecho respaldado por un estándar - ISO8601. El formato de serialización preferido se ve así: '2012-02-07T07: 17: 00-05: 00'. Pero no estoy seguro si WCF alguna vez adoptó esto correctamente o no. –

Respuesta

1

En mi humilde opinión el mayor dolor de cabeza en el uso de DateTime con un servicio WCF es que WCF actualmente no es compatible con xs: Fecha - vea this related question y las sugerencias de Connect vinculadas.

DateTimeOffset no ayuda con este problema.

+0

Pero también, el problema DateTimeOffset no está realmente relacionado con este. – hangy

8

Actualmente estoy cambiando parte de nuestra infraestructura a WCF y tropecé con esta pregunta sin respuesta y decidí probarla. :)

La forma en que WCF serializa DateTime y DateTimeOffset parece ser un poco raro. Como muestra la siguiente muestra, utilizando DateTime se parece a la mejor opción cuando se trabaja con otras plataformas:

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; } 
} 

La respuesta XML de la solicitud es:

<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> 

estoy en la zona horaria GMT + 01.00 , entonces los valores parecen ser correctos. ¿Por qué es así? Pues bien, el WSDL define Container así:

<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> 

Y DateTimeOffset - en WSDL - se define como:

<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> 

Así que, básicamente, DateTime es serializado como un estándar xs:dateTime (que tiene la zona horaria correcta componente) y DateTimeOffset se serializa en un tipo complejo no estándar, que la persona que llama debería comprender y manejar correctamente.

FWIW; Desde que descubrí esto, probablemente usaré DateTime para la interfaz WCF a menos que realmente deba ocuparme de diferentes desplazamientos de la zona horaria.

En la actualidad, la única justificación que pude ver a favor de usar el tipo complejo (ya xs:dateTime debe ser capaz de contener toda la información que lo hace!) Es que si xs:dateTime se había utilizado para serializar DateTime y DateTimeOffset, un cliente WCF no tendría idea qué tipo de usar.

Cuestiones relacionadas