66 votes

Suppression des types de valeurs nulles émis par XmlSerializer

Veuillez considérer la propriété de type valeur du montant suivante qui est marquée comme un XmlElement nullable :

[XmlElement(IsNullable=true)] 
public double? Amount { get ; set ; }

Lorsqu'un type de valeur nullable est défini sur null, le résultat de C# XmlSerializer ressemble à ce qui suit :

<amount xsi:nil="true" />

Plutôt que d'émettre cet élément, je voudrais que le XmlSerializer le supprime complètement. Pourquoi ? Nous utilisons Authorize.NET pour les paiements en ligne et Authorize.NET rejette la demande si cet élément nul existe.

La solution actuelle consiste à ne pas sérialiser du tout la propriété Amount value type. Au lieu de cela, nous avons créé une propriété complémentaire, SerializableAmount, qui est basée sur Amount et est sérialisée à la place. Puisque SerializableAmount est de type String, qui comme les types de référence sont supprimés par le XmlSerializer s'ils sont nuls par défaut, tout fonctionne parfaitement.

/// <summary>
/// Gets or sets the amount.
/// </summary>
[XmlIgnore]
public double? Amount { get; set; }

/// <summary>
/// Gets or sets the amount for serialization purposes only.
/// This had to be done because setting value types to null 
/// does not prevent them from being included when a class 
/// is being serialized.  When a nullable value type is set 
/// to null, such as with the Amount property, the result 
/// looks like: &gt;amount xsi:nil="true" /&lt; which will 
/// cause the Authorize.NET to reject the request.  Strings 
/// when set to null will be removed as they are a 
/// reference type.
/// </summary>
[XmlElement("amount", IsNullable = false)]
public string SerializableAmount
{
    get { return this.Amount == null ? null : this.Amount.ToString(); }
    set { this.Amount = Convert.ToDouble(value); }
}

Bien sûr, il ne s'agit que d'une solution de rechange. Existe-t-il un moyen plus propre de supprimer l'émission des éléments de type valeur nulle ?

5 votes

Btw ; "amount" (pour les paiements) peut être mieux utilisé comme decimal .

1 votes

Bon point : la monnaie à virgule flottante est diabolique.

0 votes

Merci de l'avoir signalé également.

137voto

Marc Gravell Points 482669

Essayez d'ajouter :

public bool ShouldSerializeAmount() {
   return Amount != null;
}

Il existe un certain nombre de modèles reconnus par certaines parties du cadre. Pour plus d'informations, XmlSerializer cherche également public bool AmountSpecified {get;set;} .

Exemple complet (passant également à decimal ) :

using System;
using System.Xml.Serialization;

public class Data {
    public decimal? Amount { get; set; }
    public bool ShouldSerializeAmount() {
        return Amount != null;
    }
    static void Main() {
        Data d = new Data();
        XmlSerializer ser = new XmlSerializer(d.GetType());
        ser.Serialize(Console.Out, d);
        Console.WriteLine();
        Console.WriteLine();
        d.Amount = 123.45M;
        ser.Serialize(Console.Out, d);
    }
}

Plus d'informations sur ShouldSerialize* sur MSDN .

3 votes

Salut Marc, c'est pour ça que j'aime SO... On apprend quelque chose comme ça. J'ai cependant quelques questions. Je ne peux trouver que la documentation suivante de cette fonctionnalité dans msdn : msdn.microsoft.com/fr/us/library/53b8022e.aspx Connaissez-vous des réel la documentation ? De plus, comme cette fonctionnalité est si peu documentée, je me sentirais un peu mal à l'aise de l'utiliser. Est-il "sûr" d'utiliser une fonction apparemment non documentée comme celle-ci ?

5 votes

Wow, c'est ce que j'appellerais profondément obscur. Cool que vous l'ayez trouvé, cependant.

0 votes

Merci Marc. Maintenant que tu m'as dit ce qu'il fallait chercher, je pense avoir trouvé la référence MSDN sur le modèle "property + specified" de XmlSerializer. C'est ici : msdn.microsoft.com/fr/us/library/ . Il est même difficile à trouver une fois que vous avez trouvé la bonne page de référence MSDN si vous voulez mon avis :) Merci encore.

6voto

mko Points 520

Il existe également une alternative pour obtenir

 <amount /> instead of <amount xsi:nil="true" />

Utilisez

[XmlElement("amount", IsNullable = false)]
public string SerializableAmount
{
    get { return this.Amount == null ? "" : this.Amount.ToString(); }
    set { this.Amount = Convert.ToDouble(value); }
}

-1voto

Vous pouvez essayer ceci :

xml.Replace("xsi:nil=\"true\"", string.Empty);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X