I was spending some time composing Soap Messages using System.Xml, but I found a strange behavior of  System.Xml while adding nodes to an existing XmlDocument.


I have an empty soap envelope like this:


string soapEnvelope = "<s:env xmlns:s='soap'><s:body /></s:env>";


What I want is to add the method payload from the next information:


string methodName = "m";

string ns="urn:ns";

string methodBody = "<name>rido</name>";             


My first attempt was a mix between AppendChild and InnerXml


XmlDocument doc = new XmlDocument();


XmlElement methodNode =  doc.CreateElement(methodName, ns);                                                      

methodNode.InnerXml = methodBody;              

XmlNode body = doc.GetElementsByTagName("s:body")[0];            



However the result output was


<s:env xmlns:s="soap">


    <m xmlns="urn:ns">

      <name xmlns="">rido</name>





Note the empty namespace declaration in the name element, and the bad news is that ASP.Net needs the namespace information to deserialize the request message, so I have to hack System.Xml to avoid this behavior.


I take a look to news://microsoft.public.dotnet.xml and I only a found a few messages talking about how to remove the attribute once the final message is composed, but I would like to avoid the empty namespace (xmlns=””) while composing the doc. After playing a little bit with the API I found the solution:


Instead of creating the method element with AppendChild, I’m going to manually build the whole method element in a string, and assign it to the body InnerXml property:


XmlDocument doc = new XmlDocument();


XmlNode body = doc.GetElementsByTagName("s:body")[0];            

string methodXml = String.Format("<{0} xmlns='{1}'>{2}</{0}>",

      methodName, ns, methodBody);

body.InnerXml = methodXml;



Now it works…