views:

962

answers:

3

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.

A: 

The two representations are equiavalent. Why do you need it to appear in the latter form?

jonnii
Because when I try to use SoapEnvelope to LoadXml it gives me the Root Element Not Found
ThorDivDev
+4  A: 

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);
Marcus Griep
This is a great answer, but I still think it's best to leave this alone, because they are equivalent.
jonnii
That depends upon the compliance of the consumer. If the consumer of the generated XML doesn't understand the shorthand notation, then this might be needed.
Marcus Griep
Who is innerwriter?
ThorDivDev
A: 

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 is the only technology that should be used for .NET web services going forward.

John Saunders
duly noted. Thank you for your response.
ThorDivDev