Cannot pass argument to CFC in Ajax call -- ends up 0 every time.

I have a message forum that I wrote a few years ago and have been building on ever since.  I've been wanting to add some AJAX functionality to it using the new CFAJAX feature of CF8.

I went to learncf.com and downloded their tutorial.  It runs perfectly, and I used it as a model for what I've written.

I have two instances here with the same problem.  First, I try to pass the value #userid# via my JS call to the AJAX instance, because the system does a check to see if there are any private messages waiting.

In the second case, I'm passing #threadid# because I'm using it to quickly subscribe/unsubscribe while viewing a thread.

In both cases, the CFC never receives the value.  It's always zero.  I got the first one to work by referencing #cookie.userid# in the CFC, although I know that's not good programming practice.  At least I know the CFC and the AJAX call works.

I've made sure I spelled things right... there are no case-sensitivity issues in the variable names, etc.  I've done View Source on the rendered page to ensure the value is there.  I've put an Alert() function in the AJAX call just before it makes the call, to ensure the value is still there.  It is.  I've put CFLOGs in the CFC to see what arguments.userid or arguments.thread id is, and it's zero.  I've even logged a CFDUMP and it's zero in that too.

Next, I used Firebug (addon to Firefox for those who don't know what it is -- VERY slick) to watch the actual call take place.  The value gets passed, as I see this:

http://www.sitename.com/ajax/thread.cfc?method=unSubThread&returnFormat=json&argumentCollection=%7B%22threadid%22%3A44841%7D&_cf_nodebug=true&_cf_nocache=true&_cf_clientid=4101F466737A8C82EFF3B56EFE433C0A&_cf_rc=1

And I get this back:

_cf_clientid      4101F466737A8C82EFF3B56EFE433C0A
_cf_nocache      true
_cf_nodebug      true
_cf_rc      1
argumentCollection      {"threadid":44841}
method      unSubThread
returnFormat      json

So it's getting the proper value, but for some reason, the CFC is blind to it.

I thought maybe I had a unique bug on my server setup (Win2k3, CF8 with Hotfix 2), but then I thought about the learncf.com tutorial.  One of the two pieces of that tutorial passes a parameter to its proxy.cfc and it works just fine.  So instead, something else must be weird.
RG_ENTAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

PluckaCommented:
Nice site that learncf.com ;)

I bet you are passing a variable at the script level that hasn't been created yet. Can you post the code that creates the proxy and the code that calls it, will be easy to fix I think.

0
RG_ENTAuthor Commented:
Here's the JS code that creates the proxy... I can paste in the cfc in the next post if needed.

The values below (userid and threadid) are both valid CF variablenames.  I pasted in the call to pmCount at the bottom, and then the call to the subUnsub routines below that.  In the case of #threadid# below, that value is coming out of a query (e.g. cfoutput query="whatever").

<script language="JavaScript">
	function do_subThread(threadid) {
		var instance = new thread_proxy();
		instance.setCallbackHandler(subUnsubCountSuccess);
		instance.subThread(threadid);
	}
 
	function do_unSubThread(threadid) {
		var instance = new thread_proxy();
		instance.setCallbackHandler(subUnsubCountSuccess);
		instance.unSubThread(threadid);
	}
	
	function subUnsubCountSuccess(result) {
		document.getElementById('subunsub').innerHTML = result;
	}
 
	function pmCount(userid) {
		var userid = userid;
		var instance = new pm_proxy();
		instance.setCallbackHandler(pmCountSuccess);
		instance.countPM(userid);
	}
	
	function pmCountSuccess(result) {
		document.getElementById('pm_count').innerHTML = result;
	}
</script>
 
<script language="javascript">
<cfoutput>
pmCount(#cookie.userid#);
</cfoutput>
</script>
 
<cfoutput>
<A HREF="##" onClick="do_subThread(#threadid#);" class="smalltext"><b>Subscribe</b></A>
<A HREF="##" onClick="do_unSubThread(#threadid#);" class="smalltext"><b>Unsubscribe</b></A>
</cfoutput>

Open in new window

0
PluckaCommented:
Ok so ColdFusion variables evaluate at run time.

So, I reckon that you are creating the threadid variable after this javascript code. Thus you have the script stuff at the top in your header and the variable does not have a value at that point.

Is that correct, does threadid exist, is there a <cfset thredid = somewhere above this javascript.

That would also explain why the cookie one works as cookies get created on previous page, thus it's already there.
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

RG_ENTAuthor Commented:
Hmmm.... interesting point.

Yes, the block of JS code exists right at the top, just inside by <body> tag.  The threadid value happens later, inside a cfoutput query="whatever" tag.

BUT... the function call (e.g. do_unsub) does pass the value... i.e. if I View Source, I will see "do_unsub(44681)" or whatever the actual threadid was.

Likewise, if I put an alert(threadid); in the actual do_unsub() function, just before it calls the ajax instance, it will come up with the proper value.

Make sense?

Here's a related question... request values.  Inside my CFC, I refer to my dsn as #request.dsn#.  This works fine.  I put cfset request.threadid = threadid inside my cfoutput loop in the hopes of just referencing request.threadid inside the CFC (just as I did with cookie.userid) but that failed.  Maybe this is related to what you're talking about -- the order in which stuff is being defined.
0
PluckaCommented:
No, if the stuff is in the alert and view source then it's working fine.

Perhaps the problem lies in the cfc.
0
RG_ENTAuthor Commented:
Here's the CFC in case you can see anything weird in it.  This is just the thread.cfc (the one that deals with threadid).

<cfcomponent>
 
	<cffunction name="subThread" access="remote" returntype="string">
		<cfargument name="threadid" type="numeric" required="true" />
 
			<cfset threadid = arguments.threadid>
			
			<!--- <cflog text="threadid = #threadid# (sub)." file="thread-ajax-cfc"> --->
			
			<cfsavecontent variable="result">
			<cfoutput>
			<A HREF="##" onClick="do_unSubThread(#threadid#);"><b>Unsubscribe</b></A>
			</cfoutput>
			</cfsavecontent>
 
			<cfif threadid gt 0>
 
				<cftry>
 
					<cfquery name="check_sub" datasource="#request.dsn#">
					select id 
					from threadsubs
					where userid = <cfqueryparam value="#cookie.userid#">
					and threadid = <cfqueryparam value="#threadid#">
					and active = <cfqueryparam value="1">
					and siteid = <cfqueryparam value="#request.siteid#">
					</cfquery>	
				
					<cfif check_sub.recordcount eq 0>
 
						<cfquery name="get_ids" datasource="#request.dsn#">
						select threadid, topicid, categoryid
						from threads
						where threadid = <cfqueryparam value="#threadid#">
						and siteid = <cfqueryparam value="#request.siteid#">
						</cfquery>	
				
						<cfoutput query="get_ids">
				
						<cfquery name="do_sub" datasource="#request.dsn#">
						set nocount on
						insert into threadsubs (
							active, 
							userid, 
							threadid, 
							topicid, 
							categoryid, 
							siteid, 
							date_added
						)
						values (
							<cfqueryparam value="1">, 
							<cfqueryparam value="#cookie.userid#">, 
							<cfqueryparam value="#threadid#">, 
							<cfqueryparam value="#topicid#">, 
							<cfqueryparam value="#categoryid#">, 
							<cfqueryparam value="#request.siteid#">, 
							#CreateODBCDateTime(Now())#
						)
						set nocount off
						</cfquery>
					
						</cfoutput>
					
					</cfif>
				
					<cfcatch type="database">
						<cfset result = "<b>DB Error</b">
					</cfcatch>				
			
				</cftry>
			
			<cfelse>
				<cfset result = "Error (threadid is 0)">
				
			</cfif>
 
		<cfreturn result>
		
	</cffunction>
 
 
	<cffunction name="unSubThread" access="remote" returntype="string">
		<cfargument name="threadid" type="numeric" required="true" />
 
<!--- 			<cfsavecontent variable="dump">
			<cfdump var="#arguments#">
			</cfsavecontent>
 
			<cflog text="#dump#" file="thread-ajax-cfc-dump"> --->
			
			<cfset threadid = arguments.threadid>
 
			<!--- <cflog text="threadid = #threadid# (unsub)." file="thread-ajax-cfc"> --->
 
			<cfsavecontent variable="result">
			<cfoutput>
			<A HREF="##" onClick="do_subThread(#threadid#);" class="smalltext"><b>Subscribe</b></A>
			</cfoutput>
			</cfsavecontent>
						
			<cfif threadid gt 0>
			
				<cftry>
	
					<cfquery name="do_unsub" datasource="#request.dsn#">
					set nocount on
					update threadsubs
					set active = <cfqueryparam value="0">
					where userid = <cfqueryparam value="#cookie.userid#">
					and threadid = <cfqueryparam value=" #threadid#">
					and siteid = <cfqueryparam value="#request.siteid#">
					set nocount off
					</cfquery>
	
					<cfcatch type="database">
						<cfset result = "<b>DB Error</b">
					</cfcatch>
	
				</cftry>
 
			<cfelse>
				<cfset result = "Error (threadid is 0)">
			</cfif>
 
		<cfreturn result>
		
	</cffunction>
 
	
</cfcomponent>

Open in new window

0
PluckaCommented:
I see you had a log there, is the value getting through to the log.
0
hieloCommented:
Try prefixing all the parameters that come from the form with "url."
Ex:
and threadid = <cfqueryparam value=" #url.threadid#">
0
PluckaCommented:
Call it from a browser, then view source do you get a result

http://www.sitename.com/ajax/thread.cfc?method=unSubThread&threadid44681

Does the view source result have the correct result?
0
PluckaCommented:
they are not url paramaters, thats a bad idea.
0
PluckaCommented:
The problem is almost certantly with the CFC. The browsing to that url I posted (with your domain) will confirm that.

you shouldn't be doing <cfset threadId = arguments.threadId />

That is bad, especially since you didn't var the variables. Just use arguments.threadId everywhere.
0
PluckaCommented:
I think I see the problem

<cfif check_sub.recordcount eq 0>

should that be

<cfif check_sub.recordcount neq 0>

Not equal?
0
PluckaCommented:
Ohh, no sorry that is a sub not an unsub.
0
RG_ENTAuthor Commented:
I tried the (corrected) url... it came back with my error "Error (threadid is 0)".

No, the value never makes it into the log.  It too reports 0 every time.  

I removed the cfset threadid = argumetns.threadid and replaced all instances with arguments.threadid.  Reran it just in case, no change.
0
PluckaCommented:
Ok, try this

1. Change the argument type to Any on line 4

Then add this on line 5

<cfdump var="#arguments#" output="c:\path\dump.txt" />

And tell me whats in there.
0
RG_ENTAuthor Commented:
Made the changes, and here's the contents of that dump...


struct
 
 
 
ACTION: stats
 
ALPHA: a
 
AVID: 0
 
CATID: 0
 
CSID: 0
 
DAYSBACK: -30
 
FID: 0
 
FROMUSERID: 0
 
GOBACK: [empty string]
 
LINKID: 0
 
OLDACTION: [empty string]
 
PAGE: 1
 
PHID: 0
 
PHOTOID: 0
 
PMID: 0
 
POSTHIST: -48
 
POSTID: 0
 
RSVPID: 0
 
SHOWDEL: 0
 
SITE_ID: 0
 
SPOTID: 0
 
THREADID: 0
 
THRID: 0
 
THUMBS: 0
 
TOPID: 0
 
TRY: 0
 
USERID: 0
 
VERIFY: 0
 
_CF_CLIENTID: EC0E3E7C1DEB46799A613046CAC8FA58
 
_CF_NOCACHE: true
 
_CF_NODEBUG: true
 
_CF_RC: 1

Open in new window

0
PluckaCommented:
Thats a lot of stuff, should just have threadid

I think you are calling this somwhere else with a lot of paramaters.

Is that the result in the dump when you run this from the url method and not your code?
0
RG_ENTAuthor Commented:
I re-ran it off the URL and got the same results... but fwiw, what you're seeing are a lot of cfparam'd values that I use on the site.  Those are all URL values too btw.
0
PluckaCommented:
Sorry,

That doesn't make any sense. There is no way anything should be in that arguments scope that isn't in that function, so there is something fundamentally wrong with the CFC.
0
RG_ENTAuthor Commented:
You make another good point.  I got to thinking about it and yeah, the CFC should be blind to all external values except what's passed to it, and some request, application and cookie variables, right?

Hmmm.

Rob
0
PluckaCommented:
Correct,

And since you are only dumping the arguments scope there should only be one thing for that function, and that is the threadid.
0
PluckaCommented:
I seem to recall that there might be issues with application.cfc in some configs.

Perhaps rename it so that it wont be found and do another test.
0
RG_ENTAuthor Commented:
I'm not using an Application.cfc with this site... just Application.cfm.  The codebase itself is largely CF5-based but I've been slowly modifying it to bring it up to more current levels.

Rob
0
PluckaCommented:
Ok,

Simple test

change test.cfc to just do this

Then browse to URL

http://www.domain.com/test.cfc?method=subThread&threadid=12345

Then the view source after that should show 12345 and the dump.text should have 12345

If that works, the other cfc is dodgy and this proves it.
<cfcomponent>
 
	<cffunction name="subThread" access="remote" returntype="string">
		<cfargument name="threadid" type="numeric" required="true" />
		
		<cfdump var="#arguments#" output="C:\path\dump.txt" />
 
		<cfreturn arguments.threadid />
	</cffunction>
 
</cfcomponent>

Open in new window

0
RG_ENTAuthor Commented:
Okay, here's the dump contents in the "code" window... it ran, it received threadid just fine, but there are still other values showing up in the dump.  But I did get "12345" in the browser window, which is good news.  We're definitely making progress!!!

I just had another idea so I ran another test.  I put your test.cfc file in another site's directory (a totally unrelated site to the forum, in fact one that isn't really used for anything), and ran it there.  The dump result ONLY showed threadid.

This is my cfapplication tag from the forum site:

<cfapplication name="forum" setclientcookies="no" sessionmanagement="yes">

Could that be causing trouble?



struct
 
 
 
ACTION: stats
 
ALPHA: a
 
AVID: 0
 
CATID: 0
 
CSID: 0
 
DAYSBACK: -30
 
FID: 0
 
FROMUSERID: 0
 
GOBACK: [empty string]
 
LINKID: 0
 
OLDACTION: [empty string]
 
PAGE: 1
 
PHID: 0
 
PHOTOID: 0
 
PMID: 0
 
POSTHIST: -48
 
POSTID: 0
 
RSVPID: 0
 
SHOWDEL: 0
 
SITE_ID: 0
 
SPOTID: 0
 
THREADID: 12345
 
THRID: 0
 
THUMBS: 0
 
TOPID: 0
 
TRY: 0
 
USERID: 0
 
VERIFY: 0
 
 

Open in new window

0
RG_ENTAuthor Commented:
Also... here's my cfajaxproxy tags... just in case.
<cfajaxproxy cfc="ajax.pm" jsclassname="pm_proxy" />
 
<cfajaxproxy cfc="ajax.thread" jsclassname="thread_proxy" />

Open in new window

0
PluckaCommented:
I dont think so, but there might be something else, like an onRequestEnd.cfm or something playing havoc.

Those other details are being injected from somewhere.

Also, make sure you disable template caching in dev, it's possible it's just recompiling and your calling an old version. That setting is in Administrator somewhere.

Simple test to fix that is

rename test.cfc (full version one) to newtest.cfc change your forum to point to that instead in your ajax stuff and as it's new it will recompile.
0
RG_ENTAuthor Commented:
I don't have Trusted Cache enabled (not right now anyway)...

But get this... I just put the test.cfc into the cfajaxproxy tag in place of thread.cfc.  Then I went to a page and clicked my Subscribe link (which I verified via View Source that it was going to pass a real value), and IT CAME BACK ZERO!!  The log confirmed it.

It worked fine when called from the URL in your post above, but when called through the forum code, the value got whacked.

Hmmmmm.... I think we're getting close!
0
RG_ENTAuthor Commented:
Here's another interesting tidbit... while poking around in general, I came to my browser window where I had run your previous test that you posted a half dozen or so messages back:


http://www.sitename.com/ajax/thread.cfc?method=unSubThread&threadid44681

I noticed that the = sign is missing after threadid.... I didn't realize it then, I just coped & pasted.  Well, I put the = sign in, and so now, running from the URL line, MY thread.cfc worked!!

So... it seems the cfc's work when run via URL, but not from within my code...

0
PluckaCommented:
ok, so that's good.

Can you show me the <cfajaxproxy code, perhaps your pointing to the wrong cfc?
0
RG_ENTAuthor Commented:
This is what I posted last night...

Definitely pointing to the right CFC... both thread.cfc and pm.cfc live within the ajax/ subdirectory.


<cfajaxproxy cfc="ajax.pm" jsclassname="pm_proxy" />
 
<cfajaxproxy cfc="ajax.thread" jsclassname="thread_proxy" />

Open in new window

0
RG_ENTAuthor Commented:
I've been playing with this more... I put your test.cfc in place of my thread.cfc and it only returns 0.  If I do it via URL (just like with thread.cfc) it works fine.  

0
RG_ENTAuthor Commented:
More testing has revealed that my CFC is fine.  If I put it on one of my other websites (on the same server, so it can reach the forum database), it works perfectly.  It's just within this one site that it doesn't work.  Very weird.  I even tested it in my version of this site that I put into Fusebox (5.5) over the last week, and the problem remains.  So, something about my code is messed up and causing this problem.  I'll eventually figure it out.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.