I want to be able to load a serialized xml class to a Soap Envelope. I am starting so I am not filling the innards so it appears like:
<Envelope
xmlns="http://schemas.xmlsoap.org/soap/envelope/" />
I want it to appear like:
<Envelope
xmlns="http://schemas.xmlsoap.org/soap/envelope/" ></Envelope>`
The class I wrote is this:
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://schemas.xmlsoap.org/soap/envelope/")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://schemas.xmlsoap.org/soap/envelope/",ElementName="Envelope", IsNullable = true)]
public class TestXmlEnvelope
{
[System.Xml.Serialization.XmlElement(ElementName="Body", Namespace="http://schemas.xmlsoap.org/soap/envelope/")]
public System.Collections.ArrayList Body = new System.Collections.ArrayList();
} //class TestXmlEnvelope`
I am using this as an example since other people might want it in an individual element. I am sure this must be simple but sadly I don't know the right keyword for this.
As always thanks for your help.
[Edit] The error comes when I try to use this instruction
System.Xml.Serialization.XmlSerializer xmlout = new System.Xml.Serialization.XmlSerializer(typeof(TestXmlEnvelope));
System.IO.MemoryStream memOut = new System.IO.MemoryStream();
xmlout.Serialize(memOut, envelope, namespc);
Microsoft.Web.Services.SoapEnvelope soapEnv = new Microsoft.Web.Services.SoapEnvelope();
soapEnv.Load(memOut);
It gives me error "Root Element not found".
[Edit] I fixed the error the problem was that after I serialized the object I didn't set the memOut.Position = 0. Still I hope this question helps other people that may want to do this.
The main issue here is that the XmlSerializer
calls WriteEndElement()
on the XmlWriter
when it would write an end tag. This, however, generates the shorthand <tag/>
form when there is no content. The WriteFullEndElement()
writes the end tag separately.
You can inject your own XmlTextWriter
into the middle that the serializer would then use to exhibit that functionality.
Given that serializer
is the appropriate XmlSerializer
, try this:
public class XmlTextWriterFull : XmlTextWriter
{
public XmlTextWriterFull(TextWriter sink) : base(sink) { }
public override void WriteEndElement()
{
base.WriteFullEndElement();
}
}
...
var writer = new XmlTextWriterFull(innerwriter);
serializer.Serialize(writer, obj);
[Edit] for the case of your added code, add facade constructors for:
public XmlTextWriterFull(Stream stream, Encoding enc) : base(stream, enc) { }
public XmlTextWriterFull(String str, Encoding enc) : base(str, enc) { }
Then, use the memory stream as your inner stream in the constructor as before:
System.IO.MemoryStream memOut = new System.IO.MemoryStream();
XmlTextWriterFull writer = new XmlTextWriterFull(memOut, Encoding.UTF8Encoding); //Or the encoding of your choice
xmlout.Serialize(writer, envelope, namespc);
Note for the record: The OP was using the ***Microsoft.***Web.Services.SoapEnvelope class, which is part of the extremely obsolete WSE 1.0 product. This class derived from the XmlDocument class, so it's possible that the same issues would have been seen with XmlDocument.
Under no circumstances should WSE be used for any new development, and if it is already in use, the code should be migrated as soon as possible. WCF or ASP.NET Web API are the only technologies that should be used for .NET web services going forward.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With