Using Positional URL Arguments When Invoking A ColdFusion Web Service

Posted April 21, 2011 at 10:01 AM by Ben Nadel

Tags: ColdFusion

A couple of months ago, I was super excited to find out that you could use an ArgumentCollection URL parameter when invoking a ColdFusion web service. Yesterday, I took that excitement up a notch when I discovered that this same approach to ColdFusion web services works with positional arguments. And, not only does the ArgumentCollection URL parameter work with positional arguments, each positional argument can, alternatively, be passed through independently.

To demonstrate this functionality, I have set up a very simple ColdFusion web service - Greeting.cfc. This web service just takes two Named arguments and builds a response. When we invoke this web service, we will be using ordered / positional arguments in lieu of named arguments.

Greeting.cfc

  • <cfcomponent
  • output="false"
  • hint="I provide a simple greeting method.">
  •  
  •  
  • <cffunction
  • name="sayHello"
  • access="remote"
  • returntype="string"
  • returnformat="json"
  • output="false"
  • hint="I say something to the given person.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="name"
  • type="string"
  • required="true"
  • hint="I am the person we are talking to."
  • />
  •  
  • <cfargument
  • name="compliment"
  • type="string"
  • required="false"
  • hint="I am the optional compliment."
  • />
  •  
  • <!--- Check to see if the compliment exists. --->
  • <cfif structKeyExists( arguments, "compliment" )>
  •  
  • <!--- Return just the hello with a compliment. --->
  • <cfreturn "Hello, #arguments.name#, you are #arguments.compliment#." />
  •  
  • <cfelse>
  •  
  • <!--- Return just the hello. --->
  • <cfreturn "Hello, #arguments.name#." />
  •  
  • </cfif>
  • </cffunction>
  •  
  • </cfcomponent>

Pretty straightforward stuff. Now, let's test it. In the following demo, I am going to invoke the above ColdFusion web service using positional arguments. When doing this, I am going to use two different approaches: the first approach will pass the positional arguments through as a single serialized ArgumentCollection value; the second approach will pass the positional arguments through as individual URL parameters.

  • <!--- Build the URL for the web service. --->
  • <cfset webServiceUrl = (
  • "http://" &
  • cgi.server_name &
  • getDirectoryFromPath( cgi.script_name ) &
  • "Greeting.cfc"
  • ) />
  •  
  • <!---
  • Build the arguments collection that we are going to use to
  • invoke the Greeting.cfc.
  • --->
  • <cfset webServiceArguments = {} />
  • <cfset webServiceArguments[ 1 ] = "Katie" />
  • <cfset webServiceArguments[ 2 ] = "looking super adorable" />
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Invoke the web service. In this pass, we're going to use the
  • above web service arguments structure and pass it through as
  • a serialized "argumentCollection" URL variable.
  • --->
  • <cfhttp
  • result="get"
  • method="get"
  • url="#webServiceUrl#">
  •  
  • <!--- The method we are invoking. --->
  • <cfhttpparam
  • type="url"
  • name="method"
  • value="sayHello"
  • />
  •  
  • <!--- Serialize the argument collection as JSON. --->
  • <cfhttpparam
  • type="url"
  • name="argumentCollection"
  • value="#serializeJSON( webServiceArguments )#"
  • />
  •  
  • </cfhttp>
  •  
  •  
  • <!--- Output the response. --->
  • <cfoutput>
  •  
  • <strong>ArgumentCollection Response:</strong>
  •  
  • #deserializeJSON( get.fileContent )#
  •  
  • </cfoutput>
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  • <br />
  • <br />
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <!---
  • Invoke the web service again. This time, however, rather than
  • passing in an argumentCollection URL variable, we are going to
  • pass in individual, ordered arguments as separate URL variables.
  • --->
  • <cfhttp
  • result="get"
  • method="get"
  • url="#webServiceUrl#">
  •  
  • <!--- The method we are invoking. --->
  • <cfhttpparam
  • type="url"
  • name="method"
  • value="sayHello"
  • />
  •  
  • <!---
  • Pass first argument. Notice that the NAME of the url
  • variable is the index of the positional argument.
  • --->
  • <cfhttpparam
  • type="url"
  • name="1"
  • value="#webServiceArguments[ 1 ]#"
  • />
  •  
  • <!---
  • Pass second argument. Notice that the NAME of the url
  • variable is the index of the positional argument.
  • --->
  • <cfhttpparam
  • type="url"
  • name="2"
  • value="#webServiceArguments[ 2 ]#"
  • />
  •  
  • </cfhttp>
  •  
  •  
  • <!--- Output the response. --->
  • <cfoutput>
  •  
  • <strong>Ordered Argument Response:</strong>
  •  
  • #deserializeJSON( get.fileContent )#
  •  
  • </cfoutput>

When we run the above code, we get the following output:

ArgumentCollection Response: Hello, Katie, you are looking super adorable.

Ordered Argument Response: Hello, Katie, you are looking super adorable.

This works in both ColdFusion 8 and ColdFusion 9 (NOTE: both of these probably have updaters installed). And, just so you know that there's no false correlation of behavior taking place, let's try switching the order of the parameters:

  • <cfset webServiceArguments = {} />
  • <cfset webServiceArguments[ 2 ] = "Katie" />
  • <cfset webServiceArguments[ 1 ] = "looking super adorable" />

This time, when we invoke the ColdFusion web service (in both CF8 and CF9), we get the following output:

ArgumentCollection Response: Hello, looking super adorable, you are Katie.

Ordered Argument Response: Hello, looking super adorable, you are Katie.

As you can see, ColdFusion is clearly honoring the defined position of the URL parameters, both in ArgumentCollection format and in individual parameter format. This is awesome!

NOTE: This works for both GET and POST methods.

What If My Web Service Doesn't Have CFArgument Tags

As I have demonstrated before, using positional arguments in ColdFusion can get tricky, especially across different versions of ColdFusion. As I have shown above, the URL-based, positional argument approach is consistent in ColdFusion 8 and ColdFusion 9 when you use CFArgument tags. If you do not use CFArgument tags, however, inconsistencies do pop up. If I were to strip out my CFArgument tags and use the following CFReturn statement (within my web service):

  • <cfreturn "Hello, #arguments[ 1 ]#, you are #arguments[ 2 ]#." />

... I would get the following output when using positional arguments in a ColdFusion 8 web service:

ArgumentCollection Response: Hello, Katie, you are looking super adorable.

Ordered Argument Response: Hello, Katie, you are looking super adorable.

... and I would get the following output when using positional arguments in a ColdFusion 9 web service:

ArgumentCollection Response: Hello, looking super adorable, you are Katie.

Ordered Argument Response: Hello, looking super adorable, you are Katie.

As you can see, ColdFusion 9 fails to adhere to the stated index of the given positional arguments. The take away: always use CFArgument tags. Of course, that should be pretty obvious in general. CFArgument tags allow for self-documenting code; and, other than some outlier situations involving a variable-number of arguments, I can't see any valid, rational, defendable reason for not using CFArgument tags.

One of ColdFusion's most powerful (and most subtle) features is its ability to invoke methods using both named and positional arguments. I have made extensive use of this within my ColdFusion applications. However, I am thrilled to learn that this kind of invocation duality can exist when communication with a 3rd party application through the use of ColdFusion web services. This definitely opens the door for some interesting interactions.




Reader Comments

There are no comments posted for this web log entry.

Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Jun 20, 2013 at 1:09 AM
The Beauty Of The jQuery Each() Method
my html code : <html> <head> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="nss.js"> ... read »
Jun 19, 2013 at 11:31 PM
Directive Link, $observe, And $watch Functions Execute Inside An AngularJS Context
@Ben, bunch to learn indeed, but thats fun part : ) ... read »
Jun 19, 2013 at 10:41 PM
Referencing ColdFusion Query Columns In A Loop Using Both Array And Dot Notation
Burdock-roots Are you going fat day by day? You need to be good for your family and make some money too. So we bring for you a best product that helps you to be more energetic every day. You will b ... read »
Jun 19, 2013 at 9:52 PM
Working With Inherited Collections In AngularJS
I recognize the applicability of your solution, and how easy it makes to share data across multiple views or even "submodules" of rather simple application. But it seems to me that it creat ... read »
Jun 19, 2013 at 9:38 PM
Directive Link, $observe, And $watch Functions Execute Inside An AngularJS Context
@Alesei, Glad you like it. Even after working with AngularJS for months, I still get a bunch of unexpected, "$digest is already in progress". So hard to debug sometimes! ... read »
Jun 19, 2013 at 9:36 PM
Working With Inherited Collections In AngularJS
@Mike, The relationship of $scope values is definitely an interesting thing! But it's not simple - it really forces you to understand prototypal inheritance, which is not at all a simple topic! Gla ... read »
Jun 19, 2013 at 9:35 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
@Joe, Oh, super interesting! I had only thought to url-encode the signature; but I think that's because the S3 docs actually have a special NOTE telling you to do so. It would have never occurred t ... read »
Jun 19, 2013 at 9:32 PM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
@Richard, Glad you like! Hopefully I'll have some more interesting stuff coming. This morning, I blogged a bit more about generating the pre-signed, query string authenticated URLs; but, then deeme ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools