Friday, August 23, 2002

.NET Serialization Bug

Here's a .NET serialization bug that affects both the SoapFormatter and BinaryFormatter:

If you have three or more classes that:

  1. Are part of the same inheritance hierarchy
  2. Have the same name but are in different namespaces
  3. Have a variable that is named the same

Then these objects will not be serialized properly and deserialization will either fail silently or throw an exception.

Example:

Try serializing the class T3.TestClass below using the SoapFormatter:

namespace T1 {
    [Serializable]
    public class TestClass {
        private string myValue = "test";
    }
}

namespace T2 {
    [Serializable]
    public class TestClass : T1.TestClass {
        private int myValue = 2;
    }
}

namespace T3 {
    [Serializable]
    public class TestClass : T2.TestClass {
        private int myValue = 3;
    }
}

What you will get as output is:

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:TestClass id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/FutureSource.UndoTestProject.T3/UndoTestProject%2C%20Version%3D1.0.965.20674%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Dnull">
<myValue>3</myValue>
<TestClass_x002B_myValue>2</TestClass_x002B_myValue>
<TestClass_x002B_myValue id="ref-3">test</TestClass_x002B_myValue>
</a1:TestClass>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Notice the two red lines? The variables myValue from classes T1.TestClass and T2.TestClass are improperly mapped to the same name TestClass_x002B_myValue. When the formatter later tries to deserialize this it will wrongly try to assign both the string and the integer to T2.myVaue and fail.

Cause: When three classes that are part of the same hierarchy have a variable that has the same name, the two .NET formatters will keep one name intact when serializing and encode the other two as class name+variable name. Unfortunately, it does not use the full class name (e.g. namespace + class name) when encoding but only the short class name.

Workaround: Write your own serialization surrogate that encodes variable names as variable name+height of declaring class in the hierarchy.

   12:53 PM

Content of this site is © Dejan Jelovic. All rights reserved.