views:

465

answers:

2

Hi guys, I encountered a problem with SOAP serialization and it would be great to find an answer. Here's a very simplified example:

public void Test()
{
    StringBuilder sb = new StringBuilder();
    StringWriter writer = new StringWriter(sb);

    SoapReflectionImporter importer = new SoapReflectionImporter();
    XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
    XmlSerializer serializer = new XmlSerializer(map);
    serializer.Serialize(writer, new A());
}

[Serializable]
public class A
{
    public A()
    {
        BB = new B();
    }

    public int a;

    public B BB;
}
[Serializable]
public class B
{
    public int A1 { get; set; }

    public int A2 { get; set; }
}

If I run method Test() then I get the following exception: System.InvalidOperationException: Token StartElement in state Epilog would result in an invalid XML document.

Would appreciate any help.

+1  A: 

Use XmlWriter instead of StringWriter and do a writer.WriteStartElement("root");

This will work:

Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);

SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());

StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();
Rashmi Pandit
Thanks, this helps. But I've got another problem, this time with deserization.If I override method GetHashCode() in class A and try to access property BB, then NullReferenceException appears during Deserialization. Somehow property BB equals 0, but it shouldn't.
Dmitry Lobanov
Can you post your deserialization code? i'll hav a look
Rashmi Pandit
Well, I localized the problem. Deserializator behaves itself pretty strange, it creates new instance of deserialized class (by invoking default constructor), after this it manually sets all fields and properties to their default values. That mean that it sets reference-type properties to null. And then deserializator invokes methods like GetHashCode() and Equals(). But my own realizations of these methods "know" that properties never will be null. That caused the exception. I just changed code in GetHashCode() and Equals(), now they "know" that properties can be null. Thanks for help!
Dmitry Lobanov
Okay ... great!!! Thanks for the info :)
Rashmi Pandit
The XML Serializer pays no attention to a non-default constructor, not to indexers, operators, or much of anything else. It's basically meant to serialize the public read/write properties of a class.
John Saunders
A: 

Just a note, The upper example will not work if the position of the stream is not set to the start of the stream. Like so:

Stream s = new MemoryStream();
XmlWriter writer = new XmlTextWriter(s, Encoding.UTF8);

SoapReflectionImporter importer = new SoapReflectionImporter();
XmlTypeMapping map = importer.ImportTypeMapping(typeof(A));
XmlSerializer serializer = new XmlSerializer(map);
writer.WriteStartElement("root");
serializer.Serialize(writer, new A());

s.Position = 0;
StreamReader sr = new StreamReader(s);
string data = sr.ReadToEnd();
Gregor S.