简体   繁体   中英

.NET XML Serialization error: Invalid or missing value of the choice identifier

Following instructions from:

.NET XML Serialization error (There was an error reflecting type)

Create object based on XmlChoiceIdentifier

http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlchoiceidentifierattribute(v=vs.110).aspx

I tried to Serialize an array of objects with the XmlChoiceIdentifier attribute. But apparently The Serializer requires an array and an ObservableCollection will cause the Serializer to throw and error (first link). I really need to have an ObservableCollection in order to keep the UI updated. So what I attempted to do was to have the Serialization engine access the array whilst the UI would access the Observable collection, albiet in a resource wasting fashion.

This was my "solution"

 [XmlType(IncludeInSchema = false)]
public enum ItemChoiceType
{
    [XmlEnumAttribute("Item")]
    Item,
    [XmlEnumAttribute("Macro")]
    Macro
}

[Serializable()]
public class GroupAndItemsCollection
{
    [XmlElementAttribute(IsNullable = false)]
    [XmlIgnore]
    public ItemChoiceType[] ItemTypeArray;

    [XmlAttribute(AttributeName = "name")]
    public string Group
    {
        get { return m_Group; }
        set
        {
            if (m_Group == value)
                return;
            m_Group = value;
            //OnPropertyChanged("Group");
        }
    }

    private ObservableCollection<ListItemName> m_items;
    private ListItemName[] m_itemsArray;

    [XmlIgnore]
    public ObservableCollection<ListItemName> Items
    {
        get
        {
            if (m_items != null && ItemsArray != null && m_items.Except(ItemsArray).Any())
            {
            m_items = new ObservableCollection<ListItemName>(ItemsArray);
            }
            return m_items;
        }
        set
        {
            m_items = value;
            ItemsArray = new ListItemName[m_items.Count];
            for (int i = 0; i < m_items.Count; i++)
            {
                ItemsArray[i] = m_items[i];
            }
        }
    }

[XmlChoiceIdentifier("ItemTypeArray")]
    [XmlElement(ElementName = "Item", Type = typeof(ObservableCollection<ListItemName>))]
    [XmlElement(ElementName = "Macro", Type = typeof(ObservableCollection<ListItemName>))]
    public ListItemName[] ItemsArray
    {
        get { return m_itemsArray; }
        set { m_itemsArray = value; }
    }


    public GroupAndItemsCollection()
    {
        //to expand nodes in XamDataTree
        IsExpanded = true;

        Items = new ObservableCollection<ListItemName>();
        Items.CollectionChanged += Items_CollectionChanged;
    }

    void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        ItemsArray = new ListItemName[m_items.Count];
        for (int i = 0; i < m_items.Count; i++)
        {
            ItemsArray[i] = m_items[i];
        }
    }
}

Then in my main method, I attempted to serialize by doing the following:

using (StreamWriter writer = new StreamWriter(dlg.FileName))
                    {
                        ItemChoiceType[] ic = new ItemChoiceType[]
                        {
                            ItemChoiceType.Item, 
                            ItemChoiceType.Macro
                        };
                        XmlSerializer xml = null;

                                group.ItemTypeArray = ic;
                            xml = new XmlSerializer(typeof(GroupAndItemsCollection));
                            xml.Serialize(writer, group);



                        writer.Close();
                    }

With this solution, I get the following error:

System.InvalidOperationException occurred


HResult=-2146233079
  Message=There was an error generating the XML document.
  Source=System.Xml
  StackTrace:
       at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
       at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o, XmlSerializerNamespaces namespaces)
       at System.Xml.Serialization.XmlSerializer.Serialize(TextWriter textWriter, Object o)
       at Otometrics.ICSSuite.Reports.ViewModel.EditReportVM.<InitializeCommands>b__38(Object o) in 
  InnerException: System.InvalidOperationException
       HResult=-2146233079
       Message=Invalid or missing value of the choice identifier 'ItemTypeArray' of type 'ItemChoiceType[]'.
       Source=Microsoft.GeneratedCode
       StackTrace:
            at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterCustomReportList.Write4_GroupAndItemsCollection(String n, String ns, GroupAndItemsCollection o, Boolean isNullable, Boolean needType)

Now, If I chose to neglect to try to sync the array and observable collection, serialization works... The code below serializes just fine.

[XmlType(IncludeInSchema = false)]
public enum ItemChoiceType
{
    [XmlEnumAttribute("Item")]
    Item,
    [XmlEnumAttribute("Macro")]
    Macro
}

[Serializable()]
public class GroupAndItemsCollection
{
    [XmlElementAttribute(IsNullable = false)]
    [XmlIgnore]
    public ItemChoiceType[] ItemTypeArray;

    [XmlAttribute(AttributeName = "name")]
    public string Group
    {
        get { return m_Group; }
        set
        {
            if (m_Group == value)
                return;
            m_Group = value;
            //OnPropertyChanged("Group");
        }
    }

    private ListItemName[] m_itemsArray;

[XmlChoiceIdentifier("ItemTypeArray")]
    [XmlElement(ElementName = "Item", Type = typeof(ObservableCollection<ListItemName>))]
    [XmlElement(ElementName = "Macro", Type = typeof(ObservableCollection<ListItemName>))]
    public ListItemName[] ItemsArray
    {
        get { return m_itemsArray; }
        set { m_itemsArray = value; }
    }


    public GroupAndItemsCollection()
    {
        IsExpanded = true;
    }
}

So what is it about my previous example that makes the XmlSerializer fail like this:

Message=Invalid or missing value of the choice identifier 'ItemTypeArray' of type 'ItemChoiceType[]'.

Although there are some answers that are correct about this error message. None of them worked. I wish that I could take the credit, but alas, my really smart team lead figured it out. What was happening with my code was that we used xsd2code to produce the vb for a schema that had an xmlChoiceIdentifier. What was happening was that in our business class when we were looping through the the code, the object for ItemChoiceType was outside the loop. So when it was validating the xml, the first node was good, and every node after that was not good. Although I had an ItemsElementName that had a good value, it was only one iteration and the rest of the xml validation would fail with this error.

We moved the the ItemsChoiceType inside the loop when creating the xml and Viola! Hope this helps. It might not pertain to the fix in this Stack Overflow, but it gave the same error and if your issue is the same as ours. You will see this page.

Happy Coding :)

The issue when using ![xsd2code has to do with enumeration of the nodes. Yes, it reads the first node and then it fails on others. For me it worked once I changed GenerateOrderXmlAttributes and GenerateXMLAttributes to true and change also the CollectionObjectType to Array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM