Deserializing empty or invalid xml attribute value into nullable int property using XmlSerializer

Beim Versuch in einem XML Formular ein XML Attribute mit einem nullable integer zu deserialisieren erhielt ich eine InvalidOperationException beim Erzeugen des XmlSerializers. Auf meiner Suche im Internet fand ich dann einen Beitrag, der auf die MSDN Referenz verwies:

"You cannot apply the IsNullable property to a member typed as a value type because a value type cannot contain null reference. Additionally, you cannot set this property to false for nullable value types. When such types are null reference, they will be serialized by setting xsi:nil to true."

Ich fand schlussendlich drei Optionen, die für mich in Frage kamen (wobei ich persönlich die 3 Variante inzwischen präferiere):

Option 1
Den Umweg über ShouldSerializeSortOrderSerialized vom Typ integer, wobei ShouldSerialize ein offizielles Attribut aus der MSDN-Referenz ist. Leider sind die Beispiele bei der MSDN-Referenz etwas verwirrend, da ein Teil des benötigten Codes in die Zeile mit den Kommentaren gerutscht ist. Wenn also in meinem XML-Formular das Attribut "SortOrder" einen Wert enthält, dann wird das Property SortOrderSerialized (de)serialisiert. Durch das Attribut 'XmlAttribute("SortOrder")' wird es allerdings als Attribut "SortOrder" und nicht als "SortOrderSerialized" (de)serialisiert. Das eigentliche Property "SortOrder", was hätte (de)serialisiert werden sollen, wird mittels dem "[XmlIgnore]" Attribute ignoriert. Der Nachteil dieser Variante besteht darin, dass wenn der Benutzer dem XML-Formular ein leeres Attribut oder kein Integerwert zuweist (z.B. SortOrder="" oder SortOrder="abc") führt dies zu einer eigens abgefangenen Programmexception, was leider sehr unschön ist.

[XmlAttribute("SortOrder")]
public virtual int SortOrderSerialized
{
   get
   {
      return this.SortOrder.Value;
   }
 
   set
   {
      this.SortOrder = value;
   }
}
 
[XmlIgnore]
public virtual int? SortOrder
{
   get;
   set;
}
 
public bool ShouldSerializeSortOrderSerialized()
{
   return this.SortOrder.HasValue;
}


Option 2

Das Xml Attribut als normalen String zu deserialisieren und es dann in einem zweiten Property in einen integer vom Type Nullable zu konvertieren. Wenn das Attribut leer oder ungültig ist, ergibt "SortOderInt" null, ansonsten enthält das Property den konvertierten Wert vom Typ Integer. Auf der anderen Seite wird "SortOrder" nur serialisiert, wenn es einen gültigen Wert enthält. Hier der Codeschnippsel dazu:

[XmlAttribute]
public virtual string SortOrder
{
   get;
   set;
}
 
[XmlIgnore]
public virtual int? SortOrderInt
{
   get
   {
      int sortOrder;
      if (!String.IsNullOrEmpty(this.SortOrder) && int.TryParse(this.SortOrder, out sortOrder))
      {
         return sortOrder;
      }
	  
      return null;
   }
}

public bool ShouldSerializeSortOrder()
{
   return !String.IsNullOrEmpty(this.SortOrder);
}

Option 3
Statt einem XML Attribut könnte auch ein XML Element verwendet werden. Hier sind nullable Wertetypen erlaubt und werden im XML-Code durch ein xsi:nil="true" kenntlich gemacht. Der Aufbau eines XML Pakets könnte dann also so aussehen:

XML-Version mit Elementen:

<?xml version="1.0" encoding="utf-8"?>
 <Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Person>
     <FirstName>Max</FirstName> 
     <LastName>Mustermann</LastName> 
     <PersonalNumber>4711</PersonalNumber> 
     <Age xsi:nil="true"></Age> 
   </Person> 
 </Data>

XML-Version mit (ungültigen weil nullable) Attributen:

<?xml version="1.0" encoding="utf-8"?>
 <Data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <Person FirstName="Max" LastName="Mustermann" PersonalNumber="4711" Age="not null ;-)"/>
 </Data>

Related Articles

We use cookies

We use cookies on our website. Some of them are essential for the operation of the site, while others help us to improve this site and the user experience (tracking cookies). You can decide for yourself whether you want to allow cookies or not. Please note that if you reject them, you may not be able to use all the functionalities of the site.