adamZ88 has asked for the wisdom of the Perl Monks concerning the following question:

Monks, I have the following code that is supposed to create a SOAP request like the example that I will provide. The purpose of the code is to query the RISDB of CUCM(Cisco Unified Communications Manager) and get a phone registration status. The problem is that I am not sure that my Request envelope is being constructed like it should, so I want to print the entire request envelope to see it and compare it to what Cisco provides as an example. Can you please help me in printing out my Request envelope? If possible in constructing the envelope to match the example? and finally in printing the entire response because I also do not know how to print just the part that I need. Thanks. The same code works for interfacing the AXL API and doing an SQL query for other information about the phones. I am just now knowing how to construct this request

################################################## #!/usr/bin/perl $cucm_ip = "10.74.7.52"; $user_axl = "user"; $password_axl = "password"; $path_file=$path."input.txt"; ###################################################################### +######################### $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; use SOAP::Lite; BEGIN { sub SOAP::Transport::HTTP::Client::get_basic_credentials { return ($user_axl => $password_axl) } } my $CUCM = SOAP::Lite ->uri("http://schemas.cisco.com/ast/soap") ->proxy("https://$cucm_ip:8443/realtimeservice2/services/RI +SService70?wsdl"); if (-e $path_file) { print "File exits\n"; print ON "File exits\n"; open(IN,"$path_file"); while (<IN>) { print "==\n"; $devname=""; $line=$_; chomp($line); @values=split(/\;/,$line,1); $devname=(shift @values); print "Input:".$devname."\n"; ###################################################################### +############################ my $xmlCode = "<selectCmDevice><StateInfo></StateInfo><CmSelectionCrit +eria><MaxReturnedDevices>1000</MaxReturnedDevices><DeviceClass>Any</D +eviceClass><Model>255</Model><Status>Any</Status><NodeName></NodeName +><SelectBy>Name</SelectBy><SelectItems><!--Zero or more repetitions:- +-><item><Item>$devname</Item></item></SelectItems><Protocol>Any</Prot +ocol><DownloadStatus>Any</DownloadStatus></CmSelectionCriteria></sele +ctCmDevice>"; $elem = SOAP::Data->type('xml' => $xmlCode); my $sRes = $CUCM->selectCmDevice($elem); my @devStat = $sRes->valueof('//return/row/Status'); print "Device Status:";print join (',' , @devStat);pr +int "\n"; #print "Device Type:".$_device_pkid."\n"; #print "Device Desc:".$_device_description."\n"; print "---\n"; ###################################################################### +############################### } } else { print "File not found\n"; } ###End################################################################ +#############################

Below is the example that cisco provides https://developer.cisco.com/site/sxml/documents/api-reference/risport/#selectcmdevice-request-format

<!--RisPort70 API - SelectCmDevice - Request--> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:soap="http://schemas.cisco.com/ast/soap"> <soapenv:Header/> <soapenv:Body> <soap:selectCmDevice> <soap:StateInfo></soap:StateInfo> <soap:CmSelectionCriteria> <soap:MaxReturnedDevices>1000</soap:MaxReturnedDevices> <soap:DeviceClass>Any</soap:DeviceClass> <soap:Model>255</soap:Model> <soap:Status>Any</soap:Status> <soap:NodeName></soap:NodeName> <soap:SelectBy>DirNumber</soap:SelectBy> <soap:SelectItems> <!--Zero or more repetitions:--> <soap:item> <soap:Item>6961</soap:Item> </soap:item> </soap:SelectItems> <soap:Protocol>Any</soap:Protocol> <soap:DownloadStatus>Any</soap:DownloadStatus> </soap:CmSelectionCriteria> </soap:selectCmDevice> </soapenv:Body> </soapenv:Envelope>

Replies are listed 'Best First'.
Re: Displaying SOAP Request and Response
by beech (Parson) on Mar 08, 2017 at 07:37 UTC
Re: Displaying SOAP Request and Response
by poj (Abbot) on Mar 08, 2017 at 13:30 UTC

    Take a look at SOAP::Transport::LOOPBACK, "it just returns the XML request as response"

    #!perl use strict; use SOAP::Lite; my $uri = "http://schemas.cisco.com/ast/soap"; my $CUCM = SOAP::Lite->uri($uri) ->proxy("loopback://"); $CUCM->outputxml(1); $CUCM->readable(1); $CUCM->envprefix('soapenv'); $CUCM->ns($uri,'soap'); $CUCM->autotype(0); my @items; for (6963..6965){ push @items,SOAP::Data->name( "item"=> \SOAP::Data->value( SOAP::Data->name("Item"=> $_) )); }; my $items = \SOAP::Data->value( @items ); my %select = ( "MaxReturnedDevices" => 1000, "DeviceClass" => 'Any', "Model" => 255, "Status" => 'Any', "NodeName" => '', "SelectBy" => 'DirNumber', "SelectItems" => $items, "Protocol" => 'Any', "DownloadStatus"=> 'Any' ); my $state = SOAP::Data->name('StateInfo',''); my $data = SOAP::Data->name("CMSelectionCriteria" => \%select); + my $elem = SOAP::Data->type('data' => $data); my $response = $CUCM->selectCmDevice($state,$elem); open OUT,'>','soap.xml' or die "$!"; print OUT $response; close OUT;

    also maybe try

    my $sql = "SELECT pkid, name, description FROM device WHERE name='SEP20370617E212'"; $response = $CUCM->executeSQLQuery( SOAP::Data->name('sql' => $sql) ); print $response;
    poj

      Poj You have me very close to figuring this out. I am uncertain that you are a Cisco Voice guy, so you may not have a solution to my current issues, but I will post my updated code below. I do get errors printed out to the file and the errors seem to come from Cisco Communications manager. What you could help me with is being able to set up Children for the "SelectItems" element. As you can see my updated code, I did this is a very naive way, I think.

      #!/usr/bin/perl my $cucm_ip = "10.74.13.228"; my $user_axl = "user"; my $password_axl = "password"; my $dev ="SEPE8BA70FB8CB5"; ###################################################################### +######################### $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0; use SOAP::Lite; BEGIN { sub SOAP::Transport::HTTP::Client::get_basic_credentials { return ($user_axl => $password_axl) } } my $CUCM = SOAP::Lite ->uri("http://schemas.cisco.com/ast/soap/action/#RisPort# +selectCmDevice") #->uri("http://schemas.cisco.com/ast/soap/") ->proxy("https://$cucm_ip:8443/realtimeservice/services/Ris +Port"); ###Maybe ?wsdl"); #->proxy("loopback://"); $CUCM->outputxml(1); $CUCM->readable(1); #$CUCM->envprefix('soapenv'); #$CUCM->ns($uri,'soap'); $CUCM->autotype(0); print "The Device $dev\n\n\n"; #####i################################################################ +############################# my %select =( "MaxReturnedDevices" => 200, "DeviceClass" => "Any", "Model" => 255, "Status" => 'Any', "NodeName" => '', "SelectBy" => 'Name', "SelectItems" => "<item><Item>$dev</Item></item>", "Protocol" => 'Any', "DownloadStatus" => 'Any' ); ################################################################# my $state = SOAP::Data->name('StateInfo',''); my $data = SOAP::Data->name('CmSelectionCriteria' , => \%select); my $elem = SOAP::Data->type('data' => $data); my $response = $CUCM->selectCmDevice($state,$elem); ##my $status=$response->valueof('//return/row/Status'); ##print "status is : $status\n\n"; open OUT,'>','soap.xml' or die "$!"; print OUT $response; close OUT;

      Also, I was building an envelope for a different version of CUCM than I have, please see below for the right format. I see that the elements have attributes, do I need to include those in my message? If so, how is this achieved? I know for sure there should be an attribute to the CmSelection Criteria, this is a session Id. Can you please help me include that in my code?

      <?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envel +ope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:SelectCmDevice soapenv:encodingStyle="http://schemas.xmlsoap.org +/soap/encoding/" xmlns:ns1="http://schemas.cisco.com/ast/soap/"> <StateInfo xsi:type="xsd:string"/> <CmSelectionCriteria href="#id0"/> </ns1:SelectCmDevice> <multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns2:CmSelectionCriteria" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns2="http://schemas.cisco.com/ast/soap/"> <MaxReturnedDevices xsi:type="xsd:unsignedInt">200</MaxReturnedDevice +s> <Class xsi:type="xsd:string">Any</Class> <Model xsi:type="xsd:unsignedInt">255</Model> <Status xsi:type="xsd:string">Registered</Status> <NodeName xsi:type="xsd:string" xsi:nil="true"/> <SelectBy xsi:type="xsd:string">Name</SelectBy> <SelectItems soapenc:arrayType="ns2:SelectItem[1]" xsi:type="soapenc: +Array"> <item href="#id1"/> </SelectItems> </multiRef> <multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns3:SelectItem" xmlns:ns3="http://schemas.cisco.com/ast/soap +/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <Item xsi:type="xsd:string">*</Item> </multiRef> </soapenv:Body> </soapenv:Envelope>
        set up Children for the "SelectItems" element

        I showed that here

        for (6963..6965){ push @items,SOAP::Data->name( "item"=> \SOAP::Data->value( SOAP::Data->name("Item"=> $_) )); }; . . "SelectItems" => $items,

        Just change the 6963..6965 to an array @device of your own device numbers. If they are in a file then use something like this perhaps

        open IN,'<', $path_file or die "Could not open $path_file : $!"; my @device = (); while (<IN>){ if (m/(SEP[0-9A-Z]+)/i){ push @device,$1; } } close IN;

        Note you have a error (extra comma) in this line

        my $data  = SOAP::Data->name('CmSelectionCriteria' ,  => \%select);
        poj