2010-08-20 51 views
47

Tengo un esquema XSD para algunos servicios RESTful. Cuando se utiliza junto con xsd.exe herramienta para generar código C#, XSD de xs:date genera el siguiente código:Force XmlSerializer para serializar DateTime como 'AAAA-MM-DD hh: mm: ss'

[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="date")] 
public System.DateTime time { 
    get { 
     return this.timeField; 
    } 
    set { 
     this.timeField = value; 
    } 
} 

cuando deserializar XML a objetos utilizando XmlSerializer todo parece estar bien. El problema al que me enfrento es que el servicio espera que las fechas se formateen como YYYY-MM-DD hh:mm:ss y el código generado por XSD parece producir solo YYYY-MM-DD.

Si modifico XSD manualmente al tipo xs:dateTime, el código C# generado produce: 2010-08-20T20:07:03.915039Z.

Básicamente, ¿cómo fuerzo la serialización para producir YYYY-MM-DD hh:mm:ss? ¿Hay algo que hacer con XSD o hay algo que pueda hacer para alterar el código de C# generado?

+0

trata de un error en el XSD, el tipo xs: 'date' se describe explícitamente para referirse a un * fecha *, sin la parte de tiempo! – skolima

+0

Mira en http://stackoverflow.com/questions/101533/serializing-datetime-to-time-without-milliseconds-and-gmt?answertab=votes#tab-top – TNT

Respuesta

94

En el pasado, he hecho lo siguiente para controlar la serialización de fecha y hora:

  • omitir la propiedad DateTime.
  • crear una propiedad de cadena ficticia que serializa/deserializa la manera que quiero

He aquí un ejemplo:

public class SomeClass 
{ 
    [XmlIgnore] 
    public DateTime SomeDate { get; set; } 

    [XmlElement("SomeDate")] 
    public string SomeDateString 
    { 
     get { return this.SomeDate.ToString("yyyy-MM-dd HH:mm:ss"); } 
     set { this.SomeDate = DateTime.Parse(value); } 
    } 
} 
+3

+1, Ok, he pensado en un similar solución pero me requeriría modificar el archivo generado por la herramienta para agregar '[XmlIgnore]' a la propiedad ofensiva. A pesar de que es una buena solución de una sola vez, no suena nada bien cuando el código fuente XSD a menudo se actualiza con nuevas funciones. Estoy pensando que sería mejor modificar el tipo de XSD de 'xs: date' a' xs: string' y tomarlo desde allí. – wpfwannabe

+0

Estoy de acuerdo con su análisis. Me encontré con problemas similares debido al formato que SharePoint espera que tengan las fechas. Una solución alternativa sería insistir en que el servicio sea más flexible con los formatos de fecha; sin embargo, como bien sabe, esta no siempre es una alternativa. – kbrimington

+0

Otra solución alternativa es rodar tu propio 'XmlSerializer', pero imagino que es más esfuerzo de lo que estabas buscando. – kbrimington

3

Creo que la implementación de la interfaz IXmlSerializable va a hacer un truco. Luego puede controlar cómo serializa y deserializa su objeto.

+1

Suena prometedor en términos de poder conectarlo fácilmente con todas las clases generadas como 'partial'. Por otro lado, pierdo todo lo bueno de la serialización automática de propiedad pública, así que debo reinventar la rueda. Esto no sería un problema si la clase tuviera solo un puñado de propiedades. Tiene muchos de ellos y parece una tarea desalentadora tener que mantener esto ya que XSD sufre cambios. – wpfwannabe

40

Utilice el atributo [XmlElement(DataType = "date")] para formatear el valor de su propiedad DateTime según lo necesite.

From MSDN:

Nota:
El atributo que acota el campo PublicationDate tiene una propiedad tipo de datos. No hay ningún tipo en .NET Framework que coincida con el tipo xs: date completamente. La coincidencia más cercana es System.DateTime, que almacena datos de fecha y hora. La especificación de la propiedad DataType como "fecha" garantiza que XmlSerializer solo serializará la fecha del objeto DateTime.

+6

Parece la solución más simple. Simplemente agregue el atributo '[XmlElement (DataType =" date ")]' a su propiedad – MadBender

+3

Publicación anterior, pero para serializar tanto la fecha como la hora, el atributo correcto para su propiedad sería: [XmlElement (DataType = "dateTime")] – devHead

1

Si solo necesita borrar la parte en milisegundos.Consulte:

How to truncate milliseconds off of a .NET DateTime

Y, básicamente, hacer algo como:

startDateTimeToUse = startDateTimeToUse.AddTicks(-(startDateTimeToUse.Ticks % TimeSpan.TicksPerSecond)); 
    endDate = endDate.AddTicks(-(endDate.Ticks % TimeSpan.TicksPerSecond)); 

puedo confirmar que este serializa a:

  <startDate>2015-10-31T12:13:04</startDate> 
      <endDate>2016-11-10T12:13:06</endDate> 

También debo decir que Antes despejar el milisegundos Estoy haciendo esto:

  var startDateTimeToUse = ssStartDateTime.ToUniversalTime(); 
      var endDate = DateTime.Now.ToUniversalTime(); 
      startDateTimeToUse = DateTime.SpecifyKind(startDateTimeToUse, DateTimeKind.Unspecified); 
      endDate = DateTime.SpecifyKind(endDate, DateTimeKind.Unspecified); 

cual no sé si es que tiene algún efecto sobre la serialización o no en este momento

+1

+1 Era el truco que necesitaba para evitar tocar nuestra lib de dal. DateTimeKind.Unspecified soltará el símbolo 'Z' cuando se serialice. –

+0

@JasonCapriotti: Lo he hecho para cambiar la forma en que se serializa el valor, por lo que tiene que ver con la serialización. Más simple y, de hecho, la solución que necesitaba para interactuar con lo que probablemente era un desorganizador PHP ingobernable en el otro lado –

Cuestiones relacionadas