Herong's Tutorial Notes on Web Service and SOAP
Dr. Herong Yang, Version 4.00

GetSpeech Failed - Incorrect Parameter Name c-gensym

This section provides a tutorial example on how to use a SOAP::Lite client to call a Web service with correct SOAPAction. But the test failed because of incorrect input parameter name c-gensym.

To fix the error in the previous tutorial, we need to set SOAPAction with the correct value. But how to do this? Which SOAP::Lite function to use?

Looking at the ActivePerl SOAP::Lite manual, it has this function:

on_action()
   This lets you specify a handler for on_action event. It is 
   triggered when creating SOAPAction. The default handler will set
   SOAPAction to "uri#method". You can change this behavior globally
   (see DEFAULT SETTINGS) or locally, for a particular object.

The online SOAP::Lite manual has a better explanation and two examples at http://search.cpan.org/~mkutter/SOAP-Lite-0.710.10/lib/SOAP/Lite.pm.

The second example is exactly what I need to fix my error:

.NET web services usually expect / as separator for uri and method. 
To change SOAP::Lite's behaviour to use uri/method as SOAPAction 
header, use the following code:
   $client->on_action( sub { join '/', @_ } );

Based on the above example I revised my test program as GetSpeech_SOAPAction.pl:

#- GetSpeech_SOAPAction.pl
#- Copyright (c) 2009 by Dr. Herong Yang, herongyang.com
#- All rights reserved
#
   use SOAP::Lite +trace;
   my $client = SOAP::Lite->new();
   $client->proxy('http://www.xmlme.com/WSShakespeare.asmx');

#- Fixing the SOAPAction header line - join uri and method name with /
   $client->uri('http://xmlme.com/WebServices');
   $client->on_action(sub { join '/', @_ });

#- Call the server
   my $som = $client->GetSpeech("To be, or not to be");
   my $output = $som->result;
   print $output . "\n";

Here is what I did in this program:

  • The URI string with the uri() is added to the client object. The URI will be used as part of the SOAPAction.
  • A callback function with on_action() is added to the client object. The callback function will be called to generate the "SOAPAction" header line.
  • The callback function joins two arguments, uri and method, to form the new "SOAPAction" header line value.

When executing GetSpeech_SOAPAction.pl, I got this:

C:\herong\ws_20080000\cod>GetSpeech_SOAPAction.pl
...
SOAP::Transport::HTTP::Client::send_receive: 
POST http://www.xmlme.com/WSShakespeare.asmx
Accept: text/xml
Accept: multipart/*
Content-Length: 540
Content-Type: text/xml; charset=utf-8
SOAPAction: http://xmlme.com/WebServices/GetSpeech

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
  xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/1999/XMLSchema"
  SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <namesp1:GetSpeech xmlns:namesp1="http://xmlme.com/WebServices">
      <c-gensym3 xsi:type="xsd:string">To be, or not to be</c-gensym3>
    </namesp1:GetSpeech>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
...
SOAP::Transport::HTTP::Client::send_receive: 
HTTP/1.1 500 Internal Server Error
Cache-Control: private
Connection: close
Date: ... 2009
Server: Microsoft-IIS/6.0
Content-Length: 623
Content-Type: text/xml; charset=utf-8
Client-Date: ... 2009
Client-Response-Num: 1
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <soap:Body>
    <soap:Fault>
      <faultcode>soap:Server</faultcode>
      <faultstring>
        System.Web.Services.Protocols.SoapException: 
        Server was unable to process request. ---> 
        System.NullReferenceException: Object reference not set 
          to an instance of an object.
        at WSShakespeare.Shakespeare.GetSpeech(String Request)
        --- End of inner exception stack trace ---
      </faultstring>
      <detail />
    </soap:Fault>
  </soap:Body>
</soap:Envelope>
...

The Web service server failed again with a "HTTP/1.1 500 Internal Server Error". It was caused by a different exception in the Web service process: "System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object."

The description of this exception is very generic. It tells us nothing about the root cause of the problem. But reviewing the request message in the trace output tells me that:

  • The "SOAPAction: http://xmlme.com/WebServices/GetSpeech" in the request is correct now.
  • The request message seems to be the cause of the problem. By default, SOAP::Lite puts my input parameter in an element called "c-gensym3". It should be "Request" according to the instruction page at http://www.xmlme.com/WSShakespeare.asmx?op=GetSpeech.

I will modify my program to provide the correct name for the request parameter in the next tutorial.

Last update: 2009.

Sections in This Chapter

GetSpeech Failed - Incorrect SOAPAction Header Line

GetSpeech Failed - Incorrect Parameter Name c-gensym

Using Socket Program to Request Parameter Name

GetSpeech Worked - Using SOAP::Data Class and on_action() Function

GetSpeech_SOAP_1_1.pl - SOAP::Lite for SOAP 1.1 Web Service

Dr. Herong Yang, updated in 2009
GetSpeech Failed - Incorrect Parameter Name c-gensym