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:
remote array function getArr() { return [1,2,3]; } }
component {
(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:
this.name="root";
public boolean function onApplicationStart() { public boolean function onRequestStart(string req) {
writeOutput("<h1>Global Corp!</h1>");
return true;
}
}
component {
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.
Archived Comments
Why don't you just use Application.cfc's OnCFCRequest() function?
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.
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.
Let me test. I don't believe it will hurt at all. That's just a HTTP header.
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. ;)
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.
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. :)
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?
Wow... you already provided the answer.
http://www.coldfusionjedi.c...
Thanks.
Glad you found it. Your question came in while I was presenting.