Why is my Ajax not working?

This post is more than 2 years old.

This is a topic I cover pretty often, but as I still get emails about it I figure it doesn't hurt to repeat myself. One of the number one reasons folks have issues with Ajax and ColdFusion is the use of Application.cfc and onRequestStart. If you output anything in onRequestStart, like a header, or a footer (in onRequestEnd obviously), it will always output, even when you make requests to CFCs. Let's look at a quick example of this.

I'll begin with my front end fancy Ajax application. It's incredibly complex. It's going to use jQuery to call a CFC method that returns an array. It will take the array and make a nice UL out of it. Here's the code.

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> $(document).ready(function() { $.post("test.cfc?method=getarr&returnformat=json", {}, function(res,code) { var s = "<h2>Results</h2><ul>"; for(var i=0; i<res.length; i++) { s+= "<li>"+res[i]+"</li>"; } s+="</ul>"; $("#result").html(s); },"json"); }) </script> </head>

<body> <div id="result"></div> </body> </html>

The CFC is trivial, but for completeness sake, here it is:

component {

remote array function getArr() { return [1,2,3]; }

}

(By the way, to the person who just called ColdFusion "tag soup" on Twitter... suck it.) Ok, if everything works, we should see this:

However, when I ran my code I saw this instead:

Global Corp? Eh? Turns out I had an Application.cfc file and I used onRequestStart to output a header for all my files:

component {

this.name="root";
public boolean function onApplicationStart() {  
		return true;    
}    

public boolean function onRequestStart(string req) {
	writeOutput("&lt;h1&gt;Global Corp!&lt;/h1&gt;");
		return true;	
}

}

The problems becomes more apparent when you make use of Chrome Dev Tools or Firebug. And folks, again, please please please please make use of these tools. You cannot, should not, must not, do Ajax development without them. Look at what my CFC returned:

You can see the header being output before the CFC. This is not a bug. You told ColdFusion to output the text on every request. Luckily it is easy enough to fix.

public boolean function onRequestStart(string req) { if(listLast(arguments.req,".") != "cfc") writeOutput("<h1>Global Corp!</h1>"); return true; }

I hope this helps (even if a repeat). As a reminder, I tend to recommend against using onRequestStart/End for templates just for this reason.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Joshua Siok posted on 9/26/2011 at 6:36 PM

Why don't you just use Application.cfc's OnCFCRequest() function?

Comment 2 by Raymond Camden posted on 9/26/2011 at 6:39 PM

Eh? Your comment doesn't make sense. The user had used onRequestStart for a header. They didn't want to do anything for CFC requests at all.

Comment 3 by Phillip Senn posted on 9/26/2011 at 6:57 PM

I put <cfheader name="Expires" value="#GetHttpTimeString(Now())#"> in all my onRequestStarts. Do you think that would ever interfere? BTW, My hosting company is still on cf8.

Comment 4 by Raymond Camden posted on 9/26/2011 at 7:02 PM

Let me test. I don't believe it will hurt at all. That's just a HTTP header.

Comment 5 by Raymond Camden posted on 9/26/2011 at 7:02 PM

Oh wait - I've got a script based CFC. ;) Um, I could do the include I guess. But I'll leave it up to you to convert my CFCs and test real quick. ;)

Comment 6 by Joshua Siok posted on 9/27/2011 at 6:07 PM

Sorry Ray. What I meant to say is "Would you recommend using OnRequest() and OnCFCRequest() instead of implementing this OnRequestStart() "hack"?" Then, you could implement the header/footer code into the OnRequest() function for non-cfc requests. I think you should make your last sentence of this post stand out more and maybe give a suggestion of best practice for cases like this. Personally, I think it would be better to simply rewrite how the application.cfc works instead of patching the code to accommodate CFC ajax requests like you did here.

Comment 7 by Raymond Camden posted on 9/27/2011 at 6:17 PM

Well it isn't a hack. onRequestStart always run before a request. If you add onCFCRequest, it _still_ fires, as it should, because you told CF to intercept it. The only thing onCFCRequest prevents is onRequest. So in the case of "I want an automatic header", the use of onRequestStart is valid, and still an issue for CFC calls, even if you use onCFCRequest.

But yeah - best solution is to not output crap in App.cfc. :)

Comment 8 by Doug posted on 10/11/2011 at 8:51 PM

Hey Ray,

Have you ever come across a AJAX problem where the JSON has "//" attached on the results? I'm perplexed on this one, since I've totally removed the application.cfc (in case it was adding something with the onrequest call).

An console log dump of what I'm seeing with a test of mine looks like this:

//{"test":"Hello World!"}

Any ideas?

Comment 9 by Doug posted on 10/11/2011 at 10:09 PM

Wow... you already provided the answer.

http://www.coldfusionjedi.c...

Thanks.

Comment 10 by Raymond Camden posted on 10/12/2011 at 12:22 AM

Glad you found it. Your question came in while I was presenting.