Bug 2205 - DataContractSerializer fails to deserialize KnownType(string[])
Summary: DataContractSerializer fails to deserialize KnownType(string[])
Status: NEW
Alias: None
Product: Class Libraries
Classification: Mono
Component: WCF assemblies (show other bugs)
Version: 2.10.x
Hardware: PC Windows
: Normal normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2011-11-27 21:24 UTC by ziye shi
Modified: 2015-10-10 22:57 UTC (History)
7 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test case (3.05 KB, application/zip)
2013-10-21 23:29 UTC, Brendan Zagaeski (Xamarin Support)
Details

Description ziye shi 2011-11-27 21:24:34 UTC
The code below should output "Name1,Name2". 
It works fine on .Net 4.0, but it crashes on mono.
I think this bug make the WCF service with return type "MyObject" crash too.

---------------- Source Code ---------------------

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.IO;

namespace ServiceTest
{
    [KnownType(typeof(string[]))]
    [DataContract]
    public class MyObject
    {
        [DataMember]
        public object NameList;
    }

    class Program
    {
        static void Main(string[] args)
        {
            var obj = new MyObject() { NameList = new[] { "Name1", "Name2" } };
            var ser = new DataContractSerializer(typeof(MyObject));
            var stream = new MemoryStream();
            ser.WriteObject(stream, obj);

            stream.Seek(0, SeekOrigin.Begin);
            var obj2 = (MyObject)ser.ReadObject(stream);
            var names = obj2.NameList as string[];
            Console.WriteLine(string.Join(",", names));
        }
    }
}
Comment 1 Martin Baulig 2012-11-15 10:05:57 UTC
Stack trace:

====
[martin@nathan:misc]$ mono E.exe 

Unhandled Exception:
System.InvalidOperationException: Node type Element is not supported in this operation.  (line 1, column 134)
  at System.Xml.XmlReader.ReadContentString (Boolean isText) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlReader.ReadContentString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlReader.ReadContentAsString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadContentAsString (Int32 maxStringContentLength) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadContentAsString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadElementContentAsString () [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializePrimitive (System.Type type, System.Xml.XmlReader reader, System.Xml.XmlQualifiedName qname) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer, System.String id, Boolean empty) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer, System.String id) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeObject (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeByMap (System.Xml.XmlQualifiedName name, System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Xml.XmlReader reader, System.Type declaredType, System.Runtime.Serialization.KnownTypeCollection knownTypes, IDataContractSurrogate surrogate, System.Runtime.Serialization.DataContractResolver resolver, System.Runtime.Serialization.DataContractResolver defaultResolver, System.String name, System.String ns, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlDictionaryReader reader, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.Xml.XmlDictionaryReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
  at ServiceTest.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.InvalidOperationException: Node type Element is not supported in this operation.  (line 1, column 134)
  at System.Xml.XmlReader.ReadContentString (Boolean isText) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlReader.ReadContentString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlReader.ReadContentAsString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadContentAsString (Int32 maxStringContentLength) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadContentAsString () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlDictionaryReader.ReadElementContentAsString () [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializePrimitive (System.Type type, System.Xml.XmlReader reader, System.Xml.XmlQualifiedName qname) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer, System.String id, Boolean empty) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer, System.String id) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeObject (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeByMap (System.Xml.XmlQualifiedName name, System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Xml.XmlReader reader, System.Type declaredType, System.Runtime.Serialization.KnownTypeCollection knownTypes, IDataContractSurrogate surrogate, System.Runtime.Serialization.DataContractResolver resolver, System.Runtime.Serialization.DataContractResolver defaultResolver, System.String name, System.String ns, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlDictionaryReader reader, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.Xml.XmlDictionaryReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.IO.Stream stream) [0x00000] in <filename unknown>:0 
  at ServiceTest.Program.Main (System.String[] args) [0x00000] in <filename unknown>:0 
[martin@nathan:misc]$ 
=====
Comment 2 Brendan Zagaeski (Xamarin Support) 2013-10-21 23:19:48 UTC
The "Node type Element is not supported" error seems to be caused by the way Mono serializes the object. This might ultimately be the same issue reported on bug #11801.

Compare the XML serialization from .NET:
> <MyObject xmlns="http://schemas.datacontract.org/2004/07/ServiceTest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
> 	<NameList i:type="a:ArrayOfstring" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
> 		<a:string>Name1</a:string>
> 		<a:string>Name2</a:string>
> 	</NameList>
> </MyObject>


Against the XML serialization from Mono:
> <MyObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ServiceTest">
> 	<NameList>
> 		<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">Name1</string>
> 		<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">Name2</string>
> 	</NameList>
> </MyObject>


Deserializing the Mono output using .NET [1] produces a similar error message:
"Element Data from namespace http://schemas.datacontract.org/2004/07/ServiceTest cannot have child contents to be deserialized as an object. Please use XmlNode[] to deserialize this pattern of XML."


Deserializing the .NET output in .NET works, but deserializing it in Mono causes another problem. "Type not found; name: string, namespace:" See bug #15572.



[1] 
using System;
using System.Runtime.Serialization;
using System.IO;

namespace ServiceTest
{
	[KnownType(typeof(string[]))]
	[DataContract]
	public class MyObject
	{
		[DataMember]
		public object NameList;
	}

	class Program
	{
		static void Main(string[] args)
		{
			var ser = new DataContractSerializer(typeof(MyObject));
			var stream = File.OpenRead ("Serialized.Mono.xml");
//			var stream = File.OpenRead ("Serialized.DotNet.xml");
			var obj2 = (MyObject)ser.ReadObject(stream);
			var names = obj2.NameList as string[];
			Console.WriteLine(string.Join(",", names));
		}
	}
}
Comment 3 Brendan Zagaeski (Xamarin Support) 2013-10-21 23:29:39 UTC
Created attachment 5197 [details]
Test case

In case it might be more convenient than the pasted code, here's a small zipped up project.

The project includes the XML output files from both Mono and .NET.

Running the project as-is will deserialize the Mono XML serialization.

Switching the commented lines for "ServiceTest.Serialized.Mono.xml" and "ServiceTest.Serialized.DotNet.xml" will switch to the .NET XML serialization. (This is the test scenario for bug #15572)
Comment 4 Brendan Zagaeski (Xamarin Support) 2013-11-27 01:36:09 UTC
Switching `OutputXsiType` to return `true` for CollectionTypeMap [1] causes the missing `i:type` attribute to be added as needed.

That said, I suspect there might be a counter-example where CollectionTypeMap should return `false` for OutputXsiType because this was the reason for [2].


> [1] https://github.com/mono/mono/blob/master/mcs/class/System.Runtime.Serialization/System.Runtime.Serialization/SerializationMap.cs#L599
> [2] https://github.com/mono/mono/commit/9df6e7165969a829a82479d8faee3346fdfa1ae9

Note You need to log in before you can comment on or make changes to this bug.