Modifier la sérialisation de date par défaut dans WCF

Est-il possible de changer la sérialisation / désérialisation JSON par défaut de DateTime dans WCF?

Actuellement, DateTime est sérialisé dans le format /Date(1372252162657+0200)/ , ce qui aurait dû être correct, mais je rencontre des problèmes lorsque mon serveur n’est pas au format UTC (que je ne peux pas modifier).

Toutes les données de date / heure en cours de traitement par ce service sont au format UTC. Tout fonctionne lorsque le serveur est en UTC. Cependant, les environnements de transfert / production sont définis sur GMT + 1 (Paris) et le sérialiseur part du principe que les dates / heures sont en GMT + 1, ignorant ainsi complètement l’atsortingbut Kind . Donc, comme vous le souhaiteriez, appeler DateTime.SetKind() et le définir sur UTC ne fonctionnera pas. En effet, les temps sérialisés sont retardés d’une heure.

Je peux soit faire des conversations de date bidirectionnelles (la même hypothèse est adoptée lors de la désérialisation, donc toujours à l’heure GMT + 1). Conversation de dates: heure UTC vers / depuis le serveur, mais c’est fastidieux. J’ai donc pensé que je pourrais peut-être simplement remplacer le comportement de sérialisation par défaut.

Oui, cela peut être fait en utilisant le concept appelé ” Formateurs de message

Mais Message Formatter serait difficile et hors de scope pour expliquer ici le débordement de stack. Vous pouvez vous référer à l’ extensibilité WCF: Formateurs de message

Si vous ne voulez pas gâcher cela, alors un hack est disponible.

Définissez le type de retour de chaque méthode sur Stream.

par exemple

  public Stream GetStaticData() { var objTobeReturned = something; WebOperationContext.Current.OutgoingResponse.ContentType = "application/json; charset=utf-8"; return new MemoryStream(Encoding.UTF8.GetBytes(objTobeReturned.ToJson())); } 

ici ToJson () est ma propre méthode d’extension qui convertit l’object en chaîne json à l’aide de la bibliothèque NewtonSoft.

WCF ignore la sortie du stream pour la sérialisation et le transmet tel quel à votre client.

J’espère que tu as eu ta réponse.

Juste pour développer l’extrait de code de tdelepine , voici le code que j’ai utilisé:

Dans mon service JSON WCF, j’avais une valeur DateTime (nullable) et je voulais que mon service renvoie la date dans un format plus lisible, afin que mon application iPhone puisse l’interpréter.

Voici à quoi ressemblait mon JSON, après avoir appliqué quelques modifications:

entrez la description de l'image ici

Notez le champ UpdateDateOriginal , qui est la méthode par défaut UpdateDateOriginal par WCF pour écrire DateTimes, et le champ UpdateDate , plus convivial, que j’ai créé à l’aide du code ci-dessous.

Mes lignes originales ressemblaient à ceci:

 [DataMember] public DateTime? UpdateDateOriginal { get; set; } 

… et voici les lignes pour créer la nouvelle valeur JSON UpdateDate conviviale.

 [IgnoreDataMember] public DateTime? UpdateDate { get; set; } [DataMember(Name = "UpdateDate")] private ssortingng UpdateDateSsortingng { get; set; } [OnSerializing] void OnSerializing(StreamingContext context) { if (this.UpdateDate == null) this.UpdateDateSsortingng = ""; else this.UpdateDateSsortingng = this.UpdateDate.Value.ToSsortingng("MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture); } [OnDeserialized] void OnDeserializing(StreamingContext context) { if (this.UpdateDateSsortingng == null) this.UpdateDate = null; else this.UpdateDate = DateTime.ParseExact(this.UpdateDateSsortingng, "MMM/dd/yyyy HH:mm", CultureInfo.InvariantCulture); } 

En fait, il peut être plus utile de renvoyer les valeurs DateTime au format ISO8601. Par exemple:

 UpdateTime: "2014-08-24T13:02:32", 

Pour ce faire, utilisez simplement mon code ci-dessus, mais remplacez la chaîne "MMM/dd/yyyy HH:mm" par "s" aux deux endroits.

Et si vos valeurs DateTime sont stockées en UTC, mais que vous souhaitiez que vos services WCF renvoient les valeurs dans le fuseau horaire local de l’utilisateur, vous pouvez suivre mes conseils ici:

Obtenir DateTime dans le fuseau horaire local des utilisateurs

La vie n’est pas plus facile, avec quelques exemples simples!

vous pouvez utiliser cette solution de contournement, dans la définition de votre object json

 [IgnoreDataMember] public DateTime dateObject; public ssortingng dateCustomSerialize { get { //Custom get } set { //Custom set } } 

Dans l’évaluateur, placez votre sérialisation de format personnalisé

Une solution consiste à utiliser un formateur de message pour modifier le DataContractSerializer par défaut, comme décrit dans Extensibilité de WCF – Formateurs de message .

Une autre option consiste à écrire une méthode d’extension qui charge votre object dans un stream. Vous pouvez ensuite appliquer le sérialiseur souhaité à l’object. Voir la réponse acceptée pour Remplacer le sérialiseur JSON par défaut dans WCF 4 par JSON.NET pour plus d’informations sur la procédure à suivre.

Cela ne résout pas votre problème de fuseaux horaires, mais je le posterai ici pour les autres personnes qui luttent avec WCF, ticks et DateTime.

Si vous ne voulez pas de ticks, mais d’un format de temps lisible par l’homme, vous pouvez le faire en introduisant une propriété de ssortingng supplémentaire. Ensuite, il suffit de manipuler DateTime avant de transformer la valeur en chaîne.

  [IgnoreDataMember] // Ignore the original tick date. public DateTime LastReminderDate { get { return _lastReminderDate; } set { _lastReminderDate = value; } } [DataMember] // Make sure you have a public or private setter! public ssortingng LastReminderDateText { get { return _lastReminderDate.ToSsortingng(); } set { _lastReminderDate = DateTime.Parse(value); } }