« Back to Cisco Webdialer Questions

RE: WebDialer SOAP interface Serialization issues using .NET

Combination View Flat View Tree View
Threads [ Previous | Next ]
Hi,
 
I'm using CUCM 6.1(2) and the WebDailer Soap interface with a .NET (3.5) client. I can sucessfully call the makeCall method.
 
However if i Call the getProfileSoap() method i get an error on deserializstion.
 
There is an error in XML document (1, 1411).

{"Cannot assign object of type System.String[] to an object of type System.String."}
 
"   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderWebdialerSoap.Read1_WDDeviceInfo()\r\n   at System.Xml.Serialization.XmlSerializationReader.ReadReferencingElement(String name, String ns, Boolean elementCanBeType, String& fixupReference)\r\n   at System.Xml.Serialization.XmlSerializationReader.ReadReferencedElements()\r\n   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderWebdialerSoap.Read11_getProfileSoapResponse()\r\n   at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer7.Deserialize(XmlSerializationReader reader)\r\n   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)"

 
Attached is the SOAP response that is being returned. Does anyone know how to resolve this issue
 
Attachments:

Johnatan
You've probably solved the issue by now.. but just for reference and to help everybody else struggling with this, here's the fix:
 
First let's start with the culprit: The WSDL file is incorrect. I don't know how, it is autogenerated after all, but it specifies the wrong return content for getProfileSoap:
 
<complexType name="WDDeviceInfo">
<sequence>
<element name="deviceName" type="xsd:string"/>
<element name="lines" type="xsd:string"/>
</sequence>
</complexType>
 
the lines element is the problem.. if you look at what's passing over the wire:
 
 
<deviceInfoList
soapenc:arrayType="ns2:WDDeviceInfo[2]" xsi:type="soapenc:Array">


  <item href="#id1" />



  <item href="#id2" />
</deviceInfoList>



<multiRef
id="id2"
soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:WDDeviceInfo"
xmlns:ns3="<strong class="ns">urn:WebdialerSoap" xmlns:soapenc="<strong class="ns">http://schemas.xmlsoap.org/soap/encoding/">


  <deviceName
xsi:type="xsd:string">SEP0016D43F0C3D</deviceName>


- <lines soapenc:arrayType="xsd:string[2]"
xsi:type="soapenc:Array">


  <item xsi:type="xsd:string">3351 ; p_phones</item>



  <item xsi:type="xsd:string">7423 ; p_phones</item>


  </lines>


  </multiRef>


Note that WDDeviceInfo as returned contains a string deviceName, and lines is an array of soapEnc:Arry... not a string.


So, we need to create our own WSDL file which matches what the service actually does.





This is done by updating the WDDeviceInfo definition:



<complexType name="WDDeviceInfo">
    <sequence>
     <element name="deviceName" type="xsd:string"/>
     <element name="lines" type="impl:ArrayOf_soapenc_string"/>
    </sequence>
   </complexType>



And, since there's no ArrayOf_soapenc_string definition, we need to add the following before the definition of WDDeviceInfo:


<complexType name="ArrayOf_soapenc_string">
      <complexContent>
        <restriction base="soapenc:Array">
          <attribute ref="soapenc:arrayType" wsdl:arrayType="soapenc:string[]"/>
        </restriction>
      </complexContent>
    </complexType>


And that's it.. now you have a WSDL that matches the service and getProfileSoap works.


Now if you want to import a service ref instead of using wsdl.exe /svcutil.exe, then put that WSDL on a webserver and import it. And pay attention that the reference probably now uses http instead of https, so make sure that the ccm url uses https. In my case, with WCF, the import created both a http and https config and for some reason the proper transport type (as well as the CCM url) was already in there so I was good from the getgo.

And it gets even worse with CCM7.. getProfileSoap starts mixing the old and new namespace. The getProfileSoap response is this:
 
<?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Body><ns1:getProfileSoapResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:WD70"><getProfileSoapReturn href="#id0"/></ns1:getProfileSoapResponse><multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:GetConfigResponse" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="urn:WD70"><description xsi:type="xsd:string">Success</description><deviceInfoList soapenc:arrayType="ns3:WDDeviceInfo[1]" xsi:type="soapenc:Array" xmlns:ns3="urn:WebdialerSoap"><item href="#id1"/></deviceInfoList><responseCode href="#id2"/></multiRef><multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns4:WDDeviceInfo" xmlns:ns4="urn:WebdialerSoap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"><deviceName xsi:type="xsd:string">SEP0016D43F0C3D</deviceName><lines soapenc:arrayType="xsd:string[2]" xsi:type="soapenc:Array"><item xsi:type="xsd:string">3355 ; p_phones</item><item xsi:type="xsd:string">7502 ; p_phones</item></lines></multiRef><multiRef id="id2" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="xsd:int" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</multiRef></soapenv:Body></soapenv:Envelope>
 
Note ns3 and ns4.. they use the old namespace.. the rest uses the new one. And of course .NET won't have that. Now I need to find a way to add the old namespace.

And here's how you fix it:
 
First of all in the <wsdl:definitions line, add the old namespace before the closing > :
 
xmlns:impl2="urn:WebdialerSoap"
 
Then move out the WDDeviceInfo declaration to a new schema declaration which you add before the existing schema declaration.
 
<schema targetNamespace="urn:WebdialerSoap" xmlns="http://www.w3.org/2001/XMLSchema">
     <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
     <import namespace="urn:WD70"/>
     <complexType name="WDDeviceInfo">
       <sequence>
         <element name="deviceName" type="xsd:string"/>
         <element name="lines" type="impl:ArrayOf_soapenc_string"/>
       </sequence>
     </complexType>
   </schema>
 
(you import the urn=WD70 namespace because it contains the ArrayOf_soapenc_string definition)
 
Finally, import the old namespace to the existing <schema> definition:
 
<schema targetNamespace="urn:WD70" xmlns="http://www.w3.org/2001/XMLSchema">
   <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
 
Now after that you add the following:
 
   <import namespace="urn:WebdialerSoap"/>
 
Save, load the WSDL and you're good to go.

  Thank you for the explanation, it was really useful. Therefore,  I would like to know how to access the wsdl description to make the change that you mentioned.
   Thank you in advance

Hi Steve
Is there any chance you can post the WSDL definition for me as every time i change it and re-add i keep getting same error as before?
i think its just the WSDL file i am using as it looks like same error every time
thanks
Mark

Hí Stephan,
 
It was really usefull. Thank you very much but I have the same question asked by Cristian. I don't know how to access the wsdl description to make the changes. I tried in the admin console of CCM OS, also with the web interfaces of CCM Administration and CCM OS Administration but I can not find how to edit the file.

I need help please.

Thank you in advance.

Regads.