title: Extension method to serialize generic objects as a SOAP formatted stream
body: <p>I'm having a hard time trying to figure out a generic extension method that would serialize a given object as <strong>SOAP</strong> formatted. The actual implementation looks somewhat like this:</p>
  
  <p><strong>Foobar.cs</strong></p>
  
  <pre><code>[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() {}
  }
  </code></pre>
  
  <p><strong>Lipsum.cs</strong></p>
  
  <pre><code>[Serializable, XmlRoot("lipsum"), XmlType("lipsum"), DataContract]
  public class Lipsum
  {
      private List&lt;Foobar&gt; lipsum = new List&lt;Foobar&gt;();
  
      [XmlElement("foobar"), DataMember]
      public List&lt;Foobar&gt; Lipsum { get { return lipsum; } }
  }
  </code></pre>
  
  <p>}</p>
  
  <p><strong>Extensions.cs</strong></p>
  
  <pre><code>public static void SerializeToSoap&lt;T&gt;(this Stream target, T source)
  {
      XmlTypeMapping xmlTypeMapping = (new SoapReflectionImporter().ImportTypeMapping(typeof(T)));
      XmlSerializer xmlSerializer = new XmlSerializer(xmlTypeMapping);
      xmlSerializer.Serialize(target, source);
  }
  </code></pre>
  
  <p><strong>Program.cs</strong></p>
  
  <pre><code>static void Main()
  {
      Lipsum lipsum = new Lipsum();
      lipsum.Lipsum.Add(
          new Foobar()
          {
              Foo = "Lorem",
              Bar = "Ipsum"
          }
      );
  
      using (MemoryStream persistence = new MemoryStream())
      {
          persistence.SerializeToSoap&lt;Lipsum&gt;(lipsum);
          Console.WriteLine(Encoding.Default.GetString(persistence.ToArray()));
          Console.WriteLine(Environment.NewLine);
      }
  }
  </code></pre>
  
  <p><strong>EXCEPTION</strong></p>
  
  <pre><code>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)
  </code></pre>
  
  <p>On the other hand both <strong>XML</strong> and <strong>JSON</strong> serialization (using <code>XmlSerializer</code> and <code>DataContractJsonSerializer</code> respectively) is working fine with the following expected results:</p>
  
  <pre><code>&lt;?xml version="1.0"?&gt;
  &lt;lipsum xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
    &lt;foobar foo="Lorem" bar="Ipsum" /&gt;
  &lt;/lipsum&gt;
  
  {"Lipsum":[{"Foo":"Lorem","Bar":"Ipsum"}]}
  </code></pre>
  
  <p>Any advice will be sincerely appreciated. Thanks much in advance.</p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>As one of the commenters remarked, there's a <code>SoapFormatter</code> class but given that I was aware it can't deal with generic types haven't included that snippet. So anyway this would be the code for that scenario:</p>
  
  <pre><code>public static void SerializeToSoap&lt;T&gt;(this Stream target, T source)
  {
      SoapFormatter soapFormatter = new SoapFormatter();
      soapFormatter.Serialize(target, source);
  }
  </code></pre>
  
  <p>Which throws the following exception:</p>
  
  <pre><code>Exception caught: Soap Serializer does not support serializing Generic Types : System.Collections.Generic.List`1[Foobar].
  </code></pre>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>Following the lead given by Merlyn Morgan-Graham I've been tried to feed the <code>SoapFormatter</code> with a non-generic object, so after a little juggling with <code>MemoryStream</code> I've ended up with this:</p>
  
  <pre><code>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);
      }
  }
  </code></pre>
  
  <p>Which surprisingly enough, character entities aside, outputs a decent SOAP message:</p>
  
  <pre><code>&lt;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/"&gt;
      &lt;SOAP-ENV:Body&gt;
          &lt;SOAP-ENC:string id="ref-1"&gt;
              &amp;#60;?xml version=&amp;#34;1.0&amp;#34;?&amp;#62;&amp;#60;lipsum
              xmlns:xsi=&amp;#34;http://www.w3.org/2001/XMLSchema-instance&amp;#34;
              xmlns:xsd=&amp;#34;http://www.w3.org/2001/XMLSchema&amp;#34;&amp;#62;&amp;#60;
              foobar foo=&amp;#34;Lorem&amp;#34; bar=&amp;#34;Ipsum&amp;#34;/&amp;#62;&amp;#60;/lipsum&amp;#62;
          &lt;/SOAP-ENC:string&gt;
      &lt;/SOAP-ENV:Body&gt;
  &lt;/SOAP-ENV:Envelope&gt;
  </code></pre>