Using Application.cfc for headers and footers and still want to use Ajax?

This post is more than 2 years old.

It must be something in the water. While I do not recommend using Application.cfc for header and footer layout, I've had two people in the last week ask me about this in terms of using Ajax. What they both found was that when they used Application.cfc to include a header and footer, this messed up their Ajax calls. Let's look at an example and show how we can quickly work around it.

First, here is a simple Application.cfc file that uses onRequestStart and onRequestEnd to output a header and footer:

<cfcomponent output="false">
&lt;cfset this.name = "ApplicationName"&gt;

&lt;cffunction name="onApplicationStart" returnType="boolean" output="false"&gt;
&lt;cfreturn true&gt;
&lt;/cffunction&gt;

&lt;cffunction name="onRequestStart" returnType="boolean" output="true"&gt;
	&lt;cfargument name="thePage" type="string" required="true"&gt;

	&lt;cfinclude template="header.cfm"&gt;
&lt;cfreturn true&gt;
&lt;/cffunction&gt;

&lt;cffunction name="onRequestEnd" returnType="void" output="true"&gt;
	&lt;cfargument name="thePage" type="string" required="true"&gt;
	
	&lt;cfinclude template="footer.cfm"&gt;
	
&lt;/cffunction&gt;

</cfcomponent>

Here is my header.cfm and footer.cfm files respectively:

<html>

<head> <title></title> </head> <!-- yes, pink, got a problem with that? --> <body bgcolor="pink">

<p> Copyright <cfoutput>#year(now())#</cfoutput> </p> </body> </html>

Ok, so now for the interesting part - the Ajax application. This is a rather contrived example, but the code here will take a number and generate an array with that many elements. Each array item will have a random number in it. The code uses jQuery, but obviously the issue relates to Ajax in general.

<script src="jquery/jquery.js"></script> <script> $(document).ready(function() {
$.ajaxSetup({
	error:function(req,textstatus,error) {
		alert('e')
	}
})

$("#submitBtn").click(function() {
	var value = $("#number").val()
	console.log('About to run my request...')
	$.getJSON("test.cfc?method=makearr&returnFormat=json",{number:value},function(d) {
		var res = ""
		for(var i=0; i&lt;d.length;i++) {
			res += "item "+(i+1)+" is "+d[i]+"&lt;br/&gt;"
		}
		$("#result").html(res)
		console.log('Done with request')
	})
})

}) </script>

<input type="text" id="number"> <input type="submit" id="submitBtn" value="Double"> <div id="result"></div>

And finally, the last piece, the CFC:

<cfcomponent output="false">

<cffunction name="makearr" access="remote" returnType="array" output="false" secureJSON="false"> <cfargument name="number" required="true" type="any"> <cfset var arr = []> <cfset var x = "">

&lt;cfloop index="x" from="1" to="#arguments.number#"&gt;
	&lt;cfset arr[x] = randRange(1,100)&gt;
&lt;/cfloop&gt;

&lt;cfreturn arr&gt;

</cffunction>

</cfcomponent>

Ok, so hopefully I haven't lost you yet. If you run this, the result will be... nothing. Why? If you use Firebug to examine the result (and you would, right?), you can see the following:

Notice the JSON in the middle, wrapped by HTML? That HTML breaks the JSON format and prevents the front end code from correctly parsing it.

The best fix, in my opinion, is to get rid of the includes in Application.cfc. I'd use custom tag wrappers instead. But if you really want to keep them in, you can simply examine the requested template. Don't forget ColdFusion passes it to both the onRequestStart and End methods. Consider these new versions:

<cffunction name="onRequestStart" returnType="boolean" output="true"> <cfargument name="thePage" type="string" required="true">
&lt;cfif listLast(arguments.thePage,".") neq "cfc"&gt;
	&lt;cfinclude template="header.cfm"&gt;
&lt;/cfif&gt;
&lt;cfreturn true&gt;

</cffunction>

<cffunction name="onRequestEnd" returnType="void" output="true"> <cfargument name="thePage" type="string" required="true">

&lt;cfif listLast(arguments.thePage,".") neq "cfc"&gt;
	&lt;cfinclude template="footer.cfm"&gt;
&lt;/cfif&gt;

</cffunction>

In each method, I've wrapped the include with a simple check to see if the requested page ends with cfc. Hope this helps.

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate for HERE Technologies. He focuses on JavaScript, serverless 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 Scott P posted on 5/5/2009 at 6:21 AM

I use extended an Application.cfc in the directory with the cfc (or anything other) files that don't need the main onRequestStart/End. Sean Corfield has a post about extending - http://corfield.org/entry/E...

Comment 2 by Shane Zehnder posted on 5/5/2009 at 7:51 AM

Subscribing to comments.

Comment 3 by Adrian J. Moreno posted on 5/5/2009 at 5:27 PM

One of my coworkers pointed out that just dropping an empty Application.cfc in the CFC root folder bypasses calls to the application's base Application.cfc methods.

Comment 4 by Raymond Camden posted on 5/5/2009 at 5:38 PM

Nice suggestions guys.

Comment 5 by Antonio Trejos posted on 5/5/2009 at 7:01 PM

The design layer has to be implemented independently from the application layer so you only call the header and footer once per Page Refresh, rather than once per on_request event. The problem is that even the calls to functions on CFC, or any other include you reference from a CFM page, is considered by the application.cfc as another request, and so it executed the on_request_start several times on an Ajax driven page. <br>
<a href="http://churubox.blogspot.co...">I go around this by using a little old time's fusebox</a>

Comment 6 by Abram posted on 5/5/2009 at 10:02 PM

@Ray, Just curious, why do you not like to use App.cfc to wrap header/footers to layout? I've done this quite a bit and haven't seen any problems. Maybe there are gotchas that I just haven't encountered yet.

Comment 7 by Josh Curtiss posted on 5/6/2009 at 4:08 AM

Personally, I'm not fond of putting any code in Application.cfc that has to do with HTML output. As soon as you start having scripts or CFCs that are used for outputting something other than a webpage that has the look and feel of your app's navigation, you start feeling the pain the will take you down the path of not doing that anymore..! :-D

Examples: CFCs, or even CFMs that output JSON or XML, or scripts that run as scheduled tasks and you save the output to cfinclude somewhere, scripts that are loaded in frames or DIVs with Ajax, etc!

Comment 8 by Abram posted on 5/6/2009 at 5:16 AM

@Josh, Good point. My framework "detects" what type of page is being requested and either wraps it in a custom tag or not; so JSON, XML or other HTML-less output is not an issue on my end. I do see how this could cause problems though.

Comment 9 by Kumar posted on 5/8/2009 at 11:42 PM

I have a different problem with an application that is some years old and I want to add some Ajax stuff to it. The Application.cfm contains HTML code on the top, and this HTML code is basically generated on every CF page request (so when a user views a source, they see a copyright message).

Any way to work around that?

Comment 10 by Raymond Camden posted on 5/8/2009 at 11:44 PM

Just edit the App.cfm. Look at the cgi scope for the URL being requested (can't remember the name offhand), and hide the HTML for CFC requests.

Comment 11 by Noah McCollam posted on 9/23/2009 at 7:03 PM

I noticed I couldn't get my AJAX calls to work for jquery until I checked for them in my onRequestStart function inside my Application.cfc

I actually got this from somewhere else, just can't remember where off the top of my head:

<cfif listlast(arguments.TargetPage,".") is "cfc">
<cfset StructDelete(this, "onRequest") />
<cfset StructDelete(variables,"onRequest")/>
</cfif>

With this little piece of code inside my application.cfc it seems to resolve all my requests to my CFC's in jquery.

Hope this helps!!!

Comment 12 by Mitchell Griffin posted on 1/20/2010 at 6:16 PM

I wanted to say that this blog post has help me move my project along. Thanks for sharing so much good information. I was having a problem with cfajaxproxy bind giving an undefined error. After many searches I found this article and and realized the problem was in my application.cfc.