I find it difficult to find a general extension method that serializes this object as SOAP . The actual implementation looks something like this:
Foobar.cs
[Serializable, XmlRoot("foobar"), DataContract] public class Foobar { [XmlAttribute("foo"), DataMember] public string Foo { get; set; } [XmlAttribute("bar"), DataMember] public string Bar { get; set; } public Foobar() {} }
Lipsum.cs
[Serializable, XmlRoot("lipsum"), XmlType("lipsum"), DataContract] public class Lipsum { private List<Foobar> lipsum = new List<Foobar>(); [XmlElement("foobar"), DataMember] public List<Foobar> Lipsum { get { return lipsum; } } }
}
Extensions.cs
public static void SerializeToSoap<T>(this Stream target, T source) { XmlTypeMapping xmlTypeMapping = (new SoapReflectionImporter().ImportTypeMapping(typeof(T))); XmlSerializer xmlSerializer = new XmlSerializer(xmlTypeMapping); xmlSerializer.Serialize(target, source); }
Program.cs
static void Main() { Lipsum lipsum = new Lipsum(); lipsum.Lipsum.Add( new Foobar() { Foo = "Lorem", Bar = "Ipsum" } ); using (MemoryStream persistence = new MemoryStream()) { persistence.SerializeToSoap<Lipsum>(lipsum); Console.WriteLine(Encoding.Default.GetString(persistence.ToArray())); Console.WriteLine(Environment.NewLine); } }
Exception
System.InvalidOperationException: Token StartElement in state Epilog would result in an invalid XML document. at System.Xml.XmlTextWriter.AutoComplete(Token token) at System.Xml.XmlTextWriter.WriteStartElement(String prefix, String localName, String ns) at System.Xml.Serialization.XmlSerializationWriter.WriteStartElement(String name, String ns, Object o, Boolean writePrefixed, XmlSerializerNamespaces xmlns) at System.Xml.Serialization.XmlSerializationWriter.WriteArray(String name, String ns, Object o, Type type) at System.Xml.Serialization.XmlSerializationWriter.WriteReferencedElement(String name, String ns, Object o, Type ambientType) at System.Xml.Serialization.XmlSerializationWriter.WriteReferencedElements() at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1. Write4_Lipsum(Object o)
On the other hand, serializing XML and JSON (using XmlSerializer and DataContractJsonSerializer respectively) works fine with the following expected results:
<?xml version="1.0"?> <lipsum xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <foobar foo="Lorem" bar="Ipsum" /> </lipsum> {"Lipsum":[{"Foo":"Lorem","Bar":"Ipsum"}]}
Any advice would be truly appreciated. Thank you very much in advance.
UPDATE
As one commenter noted, there is a SoapFormatter class, but given that I knew that it could not deal with common types, this fragment did not include. One way or another, this will be the code for this scenario:
public static void SerializeToSoap<T>(this Stream target, T source) { SoapFormatter soapFormatter = new SoapFormatter(); soapFormatter.Serialize(target, source); }
This throws the following exception:
Exception caught: Soap Serializer does not support serializing Generic Types : System.Collections.Generic.List`1[Foobar].
UPDATE 2
Following Merlin Morgan-Graham's directions, I tried to feed the SoapFormatter non-universal object, so after a bit of juggling with MemoryStream I ended up with this:
using (MemoryStream xmlStream = new MemoryStream()) { XmlSerializer xmlSerializer = new XmlSerializer(typeof(T)); xmlSerializer.Serialize(xmlStream, lipsum); using (MemoryStream soapStream = new MemoryStream()) { SoapFormatter soapFormatter = new SoapFormatter(); soapFormatter.Serialize(soapStream, Encoding.Default.GetString(xmlStream.ToArray())); Console.WriteLine(Encoding.Default.GetString(soapStream.ToArray())); Console.WriteLine(Environment.NewLine); } }
Surprisingly, character objects aside, produce a decent SOAP message:
<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> <SOAP-ENC:string id="ref-1"> <?xml version="1.0"?><lipsum xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">< foobar foo="Lorem" bar="Ipsum"/></lipsum> </SOAP-ENC:string> </SOAP-ENV:Body> </SOAP-ENV:Envelope>