frequent
frequent

Reputation: 28483

How to pass a struct to Coldfusion CFC using CFINVOKE?

I have a CFC file which handles all of the emails I'm sending form an application (using Coldfusion8).

I was using CFINVOKE to call the respective function inside this CFC and passed a struct with all user data along like so:

<cfscript>  
var User.data = {};
    User.data.name = "John Doe";
    User.data.email = "[email protected]";
    ...
</cfscript>     
// call mailer
<cfinvoke component="mailer_user" method="say_hi">
    <cfinvokeargument name="userData" value="#User.data#">
</cfinvoke>

And inside my mailer.cfc

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="userData" type="struct" required="true" /> 
 ....

For some reason this now fails and I can only get it to work if I pass fields seperately as cfargument, which is a a pain, since I'm passing a lot of data.

Question: How can I get this to work using argumentCollection.

Even if I CFINVOKE like this:

 <cfinvoke component="mailer_user" argumentcollection="#User.data#" method="say_hi"></cfinvoke>

it still doesn't do a thing. I'm setting output flags right before the cfinvoke and after, as well as inside the "say_hi" function going in and out. I'm only getting the flag before CFINVOKE.

Side note: This is all done through AJAX and I'm only getting back success="false" if my CFC has an error somewhere. I only work remotely on the system, so I can't set AJAX debugging in CFADMIN

Upvotes: 0

Views: 3661

Answers (4)

Sanjeev
Sanjeev

Reputation: 11

You should map the variable to the data you pass, then no problem sending a struct. Do it this way

<cfset objMailer = createObject("component","mailer_user") />

<cfset objMailer.say_hi(userData:user.data)/>

This works even in CF7.

Upvotes: 1

frequent
frequent

Reputation: 28483

Ok. There was a typo inside my mailer CFC, where I had a variable with "##". As is was inside my email text it went unnoticed...

So you can pass a struct allright using this:

<cfinvoke component="mailer_user" method="say_hi">
    <cfinvokeargument name="userData" value="#User.userdata#">
</cfinvoke>

and grab it inside your called function like so:

<cffunction name="say_hi" access="public" output="false" hint=""> 
    <cfargument name="userData" type="struct" required="true" hint="user data  passed" /> 
    <cfscript>  
        var internalInfo = "";
        var User = {};
        User.userdata = userData;                   
    </cfscript> 
    ...

Maybe someone else can use the snippet.

Upvotes: 0

Stephen Moretti
Stephen Moretti

Reputation: 2438

As I typed the comment above it occurred to me what the problem is likely to be.

You are passing in a structure to your function. You pass User.data which has name,email,blah,etc as keys in that structure. Those keys need to match the arguments in your function

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="name" type="struct" required="true" /> 
    <cfargument name="email" type="struct" required="true" /> 
    <cfargument name="blah" type="struct" required="true" /> 
    <cfargument name="etc" type="struct" required="true" /> 

If you want to pass in the structure as a argument, you would need to have a user.userData as your structure of user data and your function should be

<cffunction name="say_hi" access="public" output="false">
    <cfargument name="userData" type="struct" required="true" /> 

When you pass the collection as argumentCollection you should do argumentCollection="#user#", so that the userData part matches your cfargument in the function.

Clear as mud?

Upvotes: 3

Henry
Henry

Reputation: 32885

I think you should stay in cfscript style by writing

// call mailer
mailUser = createObject("component", "mailer_user");    // or new mailer_user(); for CF9+
mailUser.say_hi(User.data);

That should work, if it doesn't, it's somewhere else in your code. Try looking at the error log.

Upvotes: 2

Related Questions