AJAX Data Requests vs. AJAX Content Requests
Over the past few days, I've noticed an increase in questions about using the new AJAX capabilities of ColdFusion 8. This is great, it means people are playing with the new version. The AJAX functionality it brings to the table are quite amazing, and it makes using AJAX a snap.
However, once people have the CF8 AJAX elements talking to the server, some confusion seems to arise. I believe this confusion is coming from a misunderstanding of the two types of AJAX requests. I see AJAX used in two ways, and how you want to interact with the server depends on what you need to do.
First there are AJAX data requests. These are requests for pure data, to be used when populating a select box, grid, etc. There is no display content here. In this case, I don't think it makes sense to try and send requests to your application controller (such as Fusebox). The UI Controller frameworks are first and foremost meant to generate content: images, tables, styles, text, etc. So when your AJAX control just needs data, bypass the UI Controller. By the way, this is also the case when the request is for Flash Remoting or a web service. For AJAX data requests, the following image shows the sequence I follow:

Second, there are AJAX content requests. These are requests for actual display elements that will be used to populate a div or an AJAX tab panel. For these requests, it does make perfect sense to go through the UI Controller. Even better, if you use a framework that supports the idea of content variables, and you are using them in your application, your work is already done. It is easy to respond to the AJAX request by rendering a small bit of content, suppressing your global page layout, and returning that content to be injected into the div or tab. CF8 makes this very easy with the new ColdFusion.navigate() JavaScript function, or by using url binding in a cfdiv. For AJAX content requests, the following image shows the sequence I would follow:

Hopefully this explains the different ways you would interact with the server depending on what you're using AJAX for. Ideas or comments welcome, as always.




Am I missing something (which wouldn't be a big surprise)?
Or even better, the whole system could be using AOP to enforce security. But that's a separate discussion.
The point is, your remote facade can leverage all the same logic that the rest of the application does. It can get references to your service CFCs from ColdSpring (or your application scope if you aren't using ColdSpring). It can access the session to check user privileges. There's really no extra work involved. Make sense?
Thanks for the clear delineation. I have been doing a lot of the latter.
Could you post a snippet of code exemplifying step 1 of the data request? I'm curious as to how you do the CFC binding (are your CFC's remote and you do the equivalent of invoking a CFC with a url...?).
<cfselect name="mediaid"
bind="cfc:art.getMedia()"
bindonload="true"
value="MediaID"
display="MediaType" />
which would populate the select box with the results of the getMedia() method call on your Art CFC. Yes, the method has to be set to "remote".
You can also do this with the new CF8 cfajaxproxy tag in CF8.
Do you know what that would look like with prototype (I'm on BD 7, but I don't think I would use the built in AJAX controls I were on CF8 anyways)? Not the select part, but the AJAX call to a CFC?
http://www.site.com/mycfc.cfc?method=yourmethod&am...
Your JavaScript would need to build up a URL like this. Also, your CFC would need to return results in JSON or WDDX format, and then you'd need to handle translating whatever was returned into something your JavaScript callback hander could use. Lastly, you'd need to write JavaScript to inject the returned data into your form control. This is all possible obviously, but without the handy stuff in CF8 it's going to be a lot more steps.
I couldnt have said it better myself... awesome post.
I kicked of a post on the yahoo Fusebox(FB) message board about problems I was having connecting my front end dsp pages to my backend CFC's taking advantage of the new CF8 Ajax features, while all going though FB. My initial problem was that I could not get the related drop down list I was working on to function with CF8's Ajax functionality, most like a bug in my code, but my post raised another interesting topic which is the source of this post/discussion.
In my company we use fusebox to talk to our backend CFC's, all information ie query's, objects etc. are passed though FB to our dsp page. All the developers working on a project understand this and use FB for both Ajax and Postback data request. To me this seems nice and clean as there is one way for getting acces to data Another reason i like this is that we have security built into the circuits of FB that control access (maybe not the best solution). So we don't need to implement security anywhere else. In your post you say that for simple data calls don't use your controller, but for HTML returned via Ajax do, To me this over complicates if from a team point of view, it easier for me to enforce that all calls go though the controller, rather than saying if you are returning queries do it this way if you need to return html do it this.
I am defiantly not saying my suggestion is correct, I'm fairly new to both CF, FB and the MVC approach of web development i just need to understanding my own head why pushing everything though the controller is not the cleanest way to do it
Cheers
Simon
First it is essential that you understand the difference between a request for data (a query) and a request for content (an HTML table). The HTML request should go through Fusebox; that is what it is for, to build and return HTML results. That is probably pretty self explanatory.
For the data request, back up a moment and think about it like this: what would you do if instead of an AJAX request, this was a SOAP web service request? Would you still send the request through Fusebox? Why not? Surely you could use Fusebox to build up the SOAP response data and header. As you say, it "seems nice and clean as there is one way for getting access to data".
OK, I'm sure after a moment of thought you would agree this is a terrible idea. ColdFusion already will generate web service responses for you. But you must let the request hit a CFC in order to do this.
Now ask yourself how you would secure this. If you have all of your security logic in Fusebox, you are going to have a hard time implementing security for your web service. What does this reveal? That the Controller is not a very good place to handle all of the security. Where you really want to wrap up the security logic is, again, in a CFC in your model. You might CALL this SecurityService CFC from your controller (in fact you almost certainly would) but the security logic itself would not be in the controller.
Ahh, and if you have a SecurityService CFC, now it is possible to use the same service to secure your web service requests. Without having to try to force the request through Fusebox.
Now back up even further. What if you want to allow Flash Remoting requests to your model from a Flex application. Now you have no choice, Fusebox cannot generate the binary AMF format no matter what you try to do. You must use a CFC. Which means by this point if you can't secure the remote method calls without having to go through Fusebox, you're out of luck.
Hopefully this is revealing the big difference between data reqeusts and content requests, as well as why you would want to refactor your system to allow for direct access to your model via CFCs. Basically, the questions to ask yourself are: How hard would it be for me to allow Flash Remoting, web services to request data? How hard would it be for me to switch frameworks from Fusebox to Mach-II? How easy is it for me to test my model, including security? The answer to all of these questions should ideally be "very easy". I think you'd agree that right now, from what you've said, then answer for you would be "very hard". Which means that you've got some thinking to do about refactoring your system as time goes on. Hopefully that helps?
cheers
Thanks for taking to the time to clearly show me where I'm would be going wrong if i was to try putting all requests though FB. You lengthly post was extremely helpful. Thanks for the time you spent.
Simon
When I try to bind it, I get the error. Any help would be appreciated.
<cfform>
<table>
<tr>
<td>Select Media Type:</td>
<td><cfselect name="mediaid"
bind="url:art.cfc?method=getmedia"
value="CountryID"
display="CountryName"
bindonload="true" method="remote" /></td>
</tr>
</table>
</cfform>
cfc:
<cfcomponent output="no">
<cfset THIS.dsn="axdealer">
<!--- Get array of media types --->
<cffunction name="getMedia" access="remote" returnType="query" >
<!--- Define variables --->
<cfset var data="">
<!--- Get data --->
<cfquery name="data" datasource="#THIS.dsn#">
SELECT Country_ID as CountryID, Country_Name as CountryName
FROM Countries
ORDER BY Country_Name
</cfquery>
<!--- And return it --->
<cfreturn data>
</cffunction>
</cfcomponent>
At the moment I have a controller circuit where a fuseaction will call the model and view circuits to construct the whole page out of content variables. If I wished to replace a traditional link with an ajax link how would this affet my overall design. Would I keep my circuits and <cfincludes> in the same place in Model Controller and View directories but populate my layout cfm page with cfdivs which call the original exit fusactions?
Does anyone have clue to what could be wrong? thanks - Jim
I've found that taking the cfform & cfc templates out and running them by themselves independatly of any other tempaltes (ie application.cfm, fusebox framework etc) then it works - but put them back into a framework of any kind and it blows up
Does anyone have the solution to this as it's driving me nuts
Cheers
Paul
I don't get any errors when I run the code. I've tried it in IE 6/7 with cfdebug on and it shows the data coming back from the cfc, but it doesn't bind with the cfinput object inside cfform. I also tried it in FF2.0 with firebug running and got the same negative results with no errors.
My next attempt will be to replace the IIS server with Apache.
If anyone out there has the bind working on a IIS/CF8 setup I'd like to know how you did it.
Thanks, Jim
I shall continue to hunt it out!