How do I include a CDATA section in a WCF client webservice call in .Net?

4.7k views Asked by At

I have been asked to create a wcf client which accesses a custom java webservice, which I can't modify. I need to consume a webservice method like:

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <createDocument xmlns="http://www.dummyUrl.com/javaws">
      <version>
        ...
        <metadata>
          <attribute name="ConfigName">ConfigurationTemplateForModuleX</attribute>
          <attribute name="ConfigValue">This is a configuration string</attribute>
        </metadata>
        ...
      </version>
    </createDocument>
  </s:Body>
</s:Envelope>

Inside the attribute "ConfigValue" I usually need to save strings, but I also need to be able to save an entire XML document inside the node as CDATA like:

        ...
        <metadata>
          <attribute name="ConfigName">ConfigurationTemplateForModuleX</attribute>
          <attribute name="ConfigValue">
          <![CDATA[
            <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            <config>
               <title>Config Template for Module X</title>
               ...
            </config>
          ]]>
          </attribute>
        </metadata>
        ...

I created a service reference to my Visual Studio project to this webservice and the proxy classes were created and I can use the webservice as described in the first code section, but the problem is that the CDATA which I want to include in the request is automatically encoded and is therefore not usable anymore because I can not change the the target webservice:

 &lt;![CDATA[
   &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;yes&quot;?&gt;
   &lt;config&gt;
     &lt;title&gt;Config Template for Module X&lt;/title&gt;
     ...
   &lt;/config&gt;
 ]]&gt;

I need somehow to modify the serilization of the XML-Text attribute, or supress the encoding.

Do you have any ideas how to solve this problem?

2

There are 2 answers

3
LocEngineer On BEST ANSWER

Convert the XML into a Base64 string and transmit that instead. A simple re-conversion on the receiving end will give you the proper XML string.

0
Daniel Martens On

One solution which is not very nice, but it works is to modify the generated C# service reference. Inside the partial class of the type I see something like this:

public partial class tKeyValuePair : object, System.ComponentModel.INotifyPropertyChanged
{
    
    private string keyField;
    
    private string valueField;
    
    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute(DataType="NMTOKEN")]
    public string key
    {
        get
        {
            return this.keyField;
        }
        set
        {
            this.keyField = value;
            this.RaisePropertyChanged("key");
        }
    }
    
    /// <remarks/>
    [System.Xml.Serialization.XmlTextAttribute()]
    public string Value
    {
        get
        {
            return this.valueField;
        }
        set
        {
            this.valueField = value;
            this.RaisePropertyChanged("Value");
        }
    }

Hint! I have created the reference with the following commandline, because the generated code is different from Visual Studio service reference:

svcutil http://server/service?wsdl /nologo /d:C:\temp\ /enableDataBinding /wrapped

When I modify the reference code of the "public string Value" and "private string valueField" to the type XmlNode[] it is possible over the C# code to create a XmlNode array with one XmlNode which has either the content of Text or the content of CDATA like:

XmlNode test = new XmlCDataSection("text in cdata");

This also works if your intention is to include valid XML as CData.