1

I am trying to deserialize a "SearchRecordList" class using the DataContractSerializer and keep getting the exception:

System.InvalidOperationException: No corresponding start element is open.

The XML i am receiving looks like this:

<?xml version=\"1.0\" encoding=\"UTF-8\"?><records type=\"array\" count=\"0\"/>

What is strange, is that if i run a test, and pass this XML string:

<?xml version=\"1.0\" encoding=\"UTF-8\"?><records type=\"array\" count=\"0\"></records>

It works fine. Any ideas what I am doing wrong? Below is the class I am deserializing to (C#, .NET 4.0):

 [XmlRoot(Namespace = "", ElementName = "records", DataType = "array")]
public class SearchRecordList:List<SearchRecord>, IXmlSerializable
{

    #region IXmlSerializable Members

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        var navigator = reader.CreateNavigator(); //returns an XPathNavigator based on the reader.
        var root = navigator.SelectSingleNode("records");

        int count;

        if (!int.TryParse(root.GetAttribute("count", ""), out count) || count < 1)
            return;

        navigator.MoveToFirstChild();

        var n = navigator.Select("record");

        AddRange(n.ToList<SearchRecord>());
    }

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        throw new System.NotImplementedException();
    }

    #endregion
}
Mike_G
  • 16,237
  • 14
  • 70
  • 101
  • Out of curiosity, have you tried testing it using the /> like the received xml is, instead of closing with ? I have no clue if that will help, but I've had some things be picky about that for some reason. – fire.eagle May 17 '11 at 18:37
  • Ya, ive passed both of the noted strings, the first one that is self closing errors out with the same exception, the second one passes. – Mike_G May 17 '11 at 18:43
  • The DataContractSerializer is not directly related to IXmlSerializable. Why are you using IXmlSerializable? – John Saunders May 17 '11 at 18:50
  • Oh, sorry. I just realized that you said that in your question and I misread it. Your code looks fine; I'm pretty sure that it's just the XPathNavigator being picky about that tag closing. I don't have a way off the top of my head to fix that though... I'll poke around a little. – fire.eagle May 17 '11 at 18:52
  • @John Saunders: IXmlSerializable is used to control the deserialization, otherwise DataContractSerializer uses its default mechanisms and adds namespaces and looks for ArrayOfSearchRecords, rathan than "records" element. – Mike_G May 17 '11 at 19:29
  • 1
    Then why even bother using the Data Contract Serializer. You're not, really - you're actually using the XML Serializer. – John Saunders May 17 '11 at 19:52
  • This post has some good insights on XmlSerializer vs. DataContractSerializer ( http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/). One of the disadvantages the author lists for DataContractSerializer is that you don't have much control over the serialized output. I feel like that is the problem you are running into here. – rsbarro May 17 '11 at 21:22
  • I dont control the output/response at all. Really the only reason I used the DataContractSerializer is because it makes casting easier. My ReadXml implimentation doesnt work for XmlSerializer (im referring to the n.ToList() i do). How could I translate that to work with the XmlSerializer? – Mike_G May 17 '11 at 21:47
  • Id love pointers guys! TBH, Im used to working with WCF and havent worked with a POX service in years. – Mike_G May 17 '11 at 21:53

2 Answers2

2

In my opinion, the DataContractSerializer should only be used to deserialize data that was serialized using the DataContractSerializer. It's just not as flexible as something like XmlSerializer. For example, the DataContractSerializer expects all XML elements to be in alphabetical order when it deserializes (see the accepted answer here: WCF web service Data Members defaulting to null). How can you guarantee that the web service you are calling is going to adhere to this requirement? To put it another way, the DataContractSerializer is not a general purpose XML deserializer, it expects data in a very specific format. To the DataContractSerializer, <records></records> and <records /> are not equivalent.

If the data you are consuming is coming from a web service, you probably should just call the web service by setting up a Service Reference. If you don't want to do that, then I would use XmlSerializer. It doesn't sound like DataContractSerializer is the right class to use in this instance.

Community
  • 1
  • 1
rsbarro
  • 27,021
  • 9
  • 71
  • 75
0

If XPath is giving you trouble you could use LINQ to XML instead. Since LINQ is not a forward-only parser, it can parse the document with out needing to know too much about its structure. http://msdn.microsoft.com/en-us/library/bb387061.aspx

Ed Charbeneau
  • 4,501
  • 23
  • 23