Coldfusion CFINVOKE parameter not working? - coldfusion

I want to invoke a cfc file on my webserver, but I always get the error: The required parameter [UserID] was not provided.
Coldfusion code:
<CFINVOKE component="changeTree" method="getTreeWidth" returnVariable="httpTreeWidth">
<cfinvokeargument name="UserID" value="#checklogin.UserID#">
</CFINVOKE>
changeTree.cfc:
<CFFUNCTION name="getTreeWidth">
<CFPARAM name="UserID" required="true">
...
Thanks for help.

In changeTree.cfc, it's suppposed to be <cfargument name="UserID" required="true"> not <cfparam>.

Related

ColdFusion function variable naming with [ ] brackets

I've got a ColdFusion handler that is taking in 3 arguments one of which is a structure. The issue I'm facing is one of the variable name contains brackets which is an illegal character in the naming of a cfargument, see example.
chargifyResponse&id=123456&event=test&payload[chargify]=testing
Any suggestions would be greatly appreciated!
Code
<cffunction name="Webhook" access="remote" output="false">
<cfargument name="id" required="false" type="string" />
<cfargument name="event" required="false" type="string" />
<cfargument name="payload&##91;chargify&##93;" required="false" type="any"/>
...
Error
Attribute validation error for CFARGUMENT.
The value of the NAME attribute is invalid.

Coldfusion - Creating SOAP Web Service

Here is the XML format that I'm trying to create a web service for:
<test a1="a1">
<e1>e1</e1>
<e2 a2="a2">
<e3>e3</e3>
<e3>e3</e3>
</e2>
</test>
My problem is that I don't know how to create a Coldfusion (cfcomponent) SOAP web service that would conform to the XML format.
This is what I have come up with:
<cfcomponent style="document" wsversion = 1 >
<cffunction name="test" returntype="String" access="remote">
<cfargument type="String" required="no" name="e1"/>
<cfargument type="xml" required="no" name="e2" />
<cfreturn "ok">
</cffunction>
</cfcomponent>
As you can see, a1,a2 and e3 are left out as I have no idea how to define them in the cffunction, and I'm not sure if making e2 as xml type is correct.
Any help is appreciated.
you have to use
<cfsavecontent variable="textxml">
<cfoutput>
<test a1="a1">
<e1>e1</e1>
<e2 a2="a2">
<e3>e3</e3>
<e3>e3</e3>
</e2>
</test>
</cfoutput>
</cfsavecontent>
and pass the testxml variable to the function as xml type argument.
<cfinvoke method="test" component="compname" xmltest="#textxml#">
no need to send seperate arguments e1 e2...can send testxml variable to the function.
<cfcomponent >
<cffunction name="test" returntype="String" access="remote">
<cfargument type="xml" required="no" name="xmltest" />
<cfset newXML = XMLParse(arguments.xmltest)>
<cfdump var="#newXML#">
<cfreturn "ok">
</cffunction>
</cfcomponent>

"Variable TotalCorpAudits is undefined" when invoking a function from cfc

I am getting Variable undefined error when i try to invoke a function from a cfc.
The best part is it is already defined above.
"IandI" is the cfc name.
Code snippet :
<cfparam name="TotalCorpAudits" default="0">
<cfset TotalAudits = TotalSiteAudits + TotalCorpAudits>
<cfinvoke component="#IandI#"
method="calcRate"
Cases="#TotalCorpAudits#"
Hours="#TotalAudits#"
iiFactor="1"
convertToPercent="true"
NumberFormatOn="true"
returnOnZeroHours="0"
returnOnNonNumericData="0"
returnvariable="TotalCorpRatioAudits"
>
Getting error at ... Cases="#TotalCorpAudits#"
CFC Code :
<cffunction name="calcRate" access="public" returntype="string"
displayname="calcs Rate" hint="" description="">
<cfargument name="Hours" required="Yes" type="string">
<cfargument name="Cases" required="Yes" type="string">
<cfargument name="IIFactor" required="No" type="numeric" default="200000">
<cfargument name="FormatMask" required="No" type="string" default="999.99">
<cfargument name="NumberFormatOn" required="No" type="boolean" default="false">
<cfargument name="returnOnZeroHours" required="No" type="string" default="0">
<cfargument name="returnOnNonNumericData" required="No" type="string" default="N/A">
<cfargument name="returnOnZeroCasesWithHours" required="No" type="string" default="0">
<cfargument name="convertToPercent" required="No" type="boolean" default="false">
CFINVOKE works like so:
<cfinvoke component="[CFC_FileName]" method="calcRate" returnvariable="TotalCorpRatioAudits">
<cfinvokeargument name="Hours" value="[whateverValueYouWant]">
<cfinvokeargument name="Cases" value="[whateverValueYouWant]">
</cfinvoke>
Notice a couple things: <cfinvokeargument> is underneath the <cfinvoke> tag. Also, I only used those two argument since they were required in the CFC, but you can add more if needed. Use https://wikidocs.adobe.com/wiki/display/coldfusionen/cfinvoke as a reference.
is the name of component comeing from a variables? Is IandI a variable? If it is not you dont have to wrap it in # signs. And that is what I think is causing the problem.
I've run into this a few times lately; it definitely seems like a bug in the ColdFusion engine. Seems as if the compiler is trying to evaluate the variable from within the CFC, rather than the calling page.
I've been able to work around it by defining my struct of arguments beforehand, then simply including the struct in the invoke().
<cfset argStruct = {argName1=val1,argName2=val2,argName3="hardcodedValue"}>
<cfinvoke component="cfcPath" method="methodName" argumentCollection="#argStruct#" />

why is it not possible to call two methods of the same component sequentially in Coldfusion?

So, I have allmost spend the night chasing a bug.... found it and no idea what is wrong.
I have script in Coldfusion which sends two emails. Both mails are in a mailer script which I'm calling with cfinvoke like so:
<cfinvoke component="form_mailer_basket" method="msg_order_seller">
... parameters
</cfinvoke>
<cfinvoke component="form_mailer_basket" method="msg_order_retailer">
... parameters
</cfinvoke>
Both mail parameters are all ok, but the 2nd mailer throws an error:
mailer orders
************************************************************************************
type: Application
************************************************************************************
message: Could not find the ColdFusion Component or Interface form_mailer_basket.
************************************************************************************
detail: Ensure that the name is correct and that the component or interface exists.
************************************************************************************
Question:
Can anyone tell me why the 2nd mail cannot find the component when the first script 5 lines above can?
Thanks!
EDIT:
Here is my code for calling both methods:
<cfif new_mail.recordcount GT 0>
<cfloop query="new_mail">
<cfset variables.newMail = new_mail.email_bestelleingang>
<cfinvoke component="form_mailer_basket" method="msg_order_seller">
<cfinvokeargument name="delDate" value="#variables.liefdatum_mail#"/>
<cfinvokeargument name="delMsg" value="#variables.bestell_text_mail#"/>
<cfinvokeargument name="delOrd" value="#LOCAL.Basket.bestelltyp#"/>
<cfinvokeargument name="mailto" value="#variables.newMail#"/>
<cfinvokeargument name="client" value="#LOCAL.Basket.re_firma#"/>
<cfinvokeargument name="rebate" value="#variables.kopf_rabatt#"/>
<cfinvokeargument name="sellerIln" value="#variables.iln_verkaeuferNEU#"/>
<cfinvokeargument name="ordNo" value="#variables.bestellnummer_neu#"/>
</cfinvoke>
</cfloop>
</cfif>
...
<cfloop query="active_check">
<cfif active_check.freigeschaltet NEQ "1" AND active_check.freigeschaltet NEQ "0">
<cfinvoke component="form_mailer_basket" method="msg_order_retailer">
<cfinvokeargument name="delDate" value="#variables.liefdatum_mail#" />
<cfinvokeargument name="delOrd" value="#LOCAL.Basket.bestelltyp#" />
<cfinvokeargument name="mailto" value="#variables.cusMail#" />
<cfinvokeargument name="client" value="#order_recipients.firma#" />
<cfinvokeargument name="rebate" value="#variables.kopf_rabatt#" />
<cfinvokeargument name="sellerIln" value="#variables.iln_verkaeuferNEU#" />
<cfinvokeargument name="ordNo" value="#variables.bestellnummer_neu#" />
<cfinvokeargument name="total" value="#variables.gesamtsumme#" />
<cfinvokeargument name="menge" value="#variables.gesamtmenge#" />
<cfinvokeargument name="curr" value="#variables.waehrung#" />
<cfinvokeargument name="agentF" value="#variables.agentFirma#" />
<cfinvokeargument name="agentN" value="#variables.agentName#" />
</cfinvoke>
</cfif>
</cfloop>
First one works, second one doesn't. Method names are correct, all parameters are ok (I know I should use an argumentsColletion...), so I'm clueless and need to take a nap. Checking back later!
And the cfc:
<cfcomponent output="false" hint="basket mailing cfc - sends out all basket related mail messages">
<!--- LOAD LANGUAGES --->
<cfinclude template="../templates/tmp_lang.cfm">
<!--- INIT --->
<cffunction name="Init" access="public" returntype="any" output="false" hint="Initialize">
<!--- nothing here for now --->
<cfreturn true />
</cffunction>
... msgs like this:
<!--- NEW ORDER SELLER --->
<cffunction name="msg_order_seller" access="public" output="false" hint="msg for new orders">
<cfargument name="delDate" type="date" required="true" hint="delivery date" />
<cfargument name="delMsg" type="string" required="true" hint="text message by retailer" />
<cfargument name="delOrd" type="string" required="true" hint="order type pre/asap" />
<cfargument name="mailto" type="string" required="true" hint="email adress" />
<cfargument name="client" type="string" required="true" hint="buyer" />
<cfargument name="rebate" type="string" required="true" hint="rebate 1/0" />
<cfargument name="sellerIln" type="string" required="true" hint="seller ILN" />
<cfargument name="ordNo" type="string" required="true" hint="order number" />
<cfprocessingdirective suppresswhitespace="No">
<cfmail
TO="#mailto#"
FROM="automailer#..."
SERVER="mail.bbb.de"
USERNAME="ddd"
PASSWORD="123456"
SUBJECT="#tx_automailer_order_new# - #client#">
#tx_automailer_default_anrede#
#tx_automailer_order_info#
#tx_automailer_order_type#: #ordertype# #rebateTxt#
#tx_automailer_order_del#: #deliveryDate#
#tx_automailer_order_no#: #ordNo#
#tx_automailer_order_date#: #DateFormat(now(),"dd.Mm.yyyy")#
#tx_kaeufer#: #client#
#tx_automailer_order_msg#:
#delMsg#
#tx_automailer_order_iln#: #sellerIln#
#tx_automailer_default_gruss#
#tx_automailer_default_team#
-------------
#tx_automailer_default_disclaimer#
</cfmail>
</cfprocessingdirective>
<cfreturn />
</cffunction>
...
</cfcomponent>
If you just want to solve your problem instead of trying to figure out what is causing it, I have a suggestion. Instead of using the cfinvoke tag for the same component many times, use either cfobject or CreateObject() to make just one instance of it. Then call the methods directly.
Even if you do get your current approach to work, it will be slower than my suggestion. cfinvoke creates an object each time you call it and that takes processing time.
Are you sure that both methods exist and are public?
Using cfinclude in cfc is NOT good practice, though admittedly I had to do it too on occasions.
Your error Could not find the ColdFusion Component or Interface form_mailer_basket seems to imply that something happens to the component itself - I suspect it has something to do with your return statement in Init() method.
In earlier versions of CF (I think around version 6/7 maybe 8) you could overwrite your function by setting identically named variable inside your cfc. You did not mention the CF version that you are running.

Can you reassign the default <cfargument in a cfc?

I'm invoking a cfc, the cfc has a default set of arguments like so:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
What I'd like to do is make these arguments not requred (as you can see by required="no") but I'd like to reassign the arguments variable if needed.
So something like:
<cfargument name="EMAIL_TEMPLATE_CODE" type="string" required="yes" hint="EMAIL_TEMPLATE_CODE is required.">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string" required="no" hint="EMAIL_TEMPLATE_SUBJECT is NOT required.">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string" required="no" hint="EMAIL_TEMPLATE_BODY is NOT required.">
<cfinvoke component="#Request.CFCPath#.email_template" method="getEmailTemplate" returnvariable="getEmailTemplate">
<cfinvokeargument name="EMAIL_TEMPLATE_CODE" value="#ARGUMENTS.EMAIL_TEMPLATE_CODE#">
</cfinvoke>
<cfif getEmailTemplate.RecordCount>
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_SUBJECT" default="#getEmailTemplate.EMAIL_TEMPLATE_SUBJECT#" type="string">
<cfparam name="ARGUMENTS.EMAIL_TEMPLATE_BODY" default="#getEmailTemplate.EMAIL_TEMPLATE_BODY#" type="string">
</cfif>
But I'm not able to override the default ARGUMENTS variable. Is there anything you can spot that I'm doing wrong?
EDIT:
I'm doing this because if no argument is passed to the cfc, I want to create one. I guess I should cfset a local variable if the argument doesn't have length?
<cfif Len(ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM)>
<cfset EMailTemplateAddressFrom = ARGUMENTS.EMAIL_TEMPLATE_ADDRESS_FROM>
<cfelse>
<cfset EMailTemplateAddressFrom = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
<cfparam> works only if the variable has been undefined before. Your function parameters are not undefined, they just happen to have their default values. So you could do this:
<cffunction name="foo">
<cfargument name="arg" type="string" required="yes">
<cfargument name="opt" default="default" type="string" required="no">
<cfif arguments.opt eq "default">
<cfset arguments.opt = "whatever dynamic value">
</cfif>
</cffunction>
This way, if you don't supply "opt" (or deliberately set it to "default"), it will get assigned some kind of dynamic default value. And you can still make it empty, if you need.
Instead of "default", you could choose some other kind of improbable value that allows you to make a distinction between "not supplied" and "empty". (Sometimes I wish ColdFusion would support actual null values...)
<cfargument name="EMAIL_TEMPLATE_CODE" type="string"
default="#getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM#">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
or....
<cfargument name="EMAIL_TEMPLATE_CODE" type="string">
<cfargument name="EMAIL_TEMPLATE_SUBJECT" default="" type="string">
<cfargument name="EMAIL_TEMPLATE_BODY" default="" type="string">
<cfif NOT isDefined("arguments.EMAIL_TEMPLATE_CODE")>
<cfset arguments.EMAIL_TEMPLATE_CODE = getEmailTemplate.EMAIL_TEMPLATE_ADDRESS_FROM>
</cfif>
FYI, required="no" by default, so I usually don't specify it to the already verbose CFML. :)