Ask a Jedi: Ajax-bound requests and onRequest

So this is definitely something I've covered more than once, but as the questions keep coming in, I'm going to keep blogging it. My real hope is that Adobe listens in here as I think this is something that really needs changing in ColdFusion. Anyway, the question, from Samer:

I found a wired case, if you use onRequest function in Application.cfc and use cfgrid with bind attribute, it always return empty query to the grid "Response is Empty" !!

Can you help?

This is a fairly simple problem. onRequest, if it exists, breaks all flash remoting and CFC calls (remote calls I mean). Make sure you understand that. It doesn't matter what you do in onRequest - the mere existence of the method will call Flash Remoting/CFC (Remote) operations fail. Period.

As I said, this is something I truly wish Adobe would just fix as all it does is trip people up.

There is a way around it. Sean Corfield has a nice little work around that involves adding the following code to your onRequestStart (not onRequest, but onRequestStart):

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

Comments

Will Swain's Gravatar Thanks Ray, I missed that post of Sean's the first time round.

As someone who has run into this problem a few times, I have to say I consider this a bug. I wonder if Adobe do too.
# Posted By Will Swain | 3/19/08 11:13 AM
Sid Wing's Gravatar BIG BIG Bug! Adobe needs to break out the flyswatter for sure on that one.
# Posted By Sid Wing | 3/19/08 12:26 PM
Michael White's Gravatar more than a bug, it's a scorpion
# Posted By Michael White | 3/20/08 12:11 PM
Don Li's Gravatar I get the impresson that application.cfc and CFC components may not play together that well for cf8 (my copy is standard). Hence, I'm a bit relunctant to change the application.cfm to application.cfc for one app which uses a handful of CFCs. I understand I may lose some efficiency...

Is Adobe all consumed with Flex and Air now?

Thks.
# Posted By Don Li | 3/21/08 8:05 PM
Raymond Camden's Gravatar Don, I'm not sure where you got this impression. There is absolutely nothing wrong with using CFCs and Application.cfc. You lose nothing moving from App.cfm - instead you gain new features.
# Posted By Raymond Camden | 3/22/08 10:37 AM
Don Li's Gravatar ok, Thank you, Ray. I'll remove my hesitation and move forward with application.cfc then.

Don
# Posted By Don Li | 3/22/08 1:57 PM
Don Li's Gravatar But Ray, I have a question, how to translate the following
code,
<cfscript>
daysForData = 3;
</cfscript>
in the application.cfm framework
to its equivalent in the application.cfc framework?

Also, it would be referenced by many (15+) templates.

Many thanks.
# Posted By Don Li | 4/1/08 7:30 PM
Raymond Camden's Gravatar That code in APp.cfm would be equivalent to the same code in onRequest.
# Posted By Raymond Camden | 4/2/08 8:27 AM
GM's Gravatar Hi Ray, I am trying to build an application and I am extending an Application.CFC my code uses onRequest in the extended Application.CFC and onRequest breaks my binding in cfselect? I tried your work around from Sean C. I am not clear on where arguments.thePage is referring to. Any help would be appreciated.
# Posted By GM | 7/24/08 1:46 PM
Raymond Camden's Gravatar Well arguments.thePage is passed to onRequest automatically. It's the page being requested. So Sean's fix is to look at the value, and if it "something.cfc", to remove itself from the request.
# Posted By Raymond Camden | 7/24/08 8:25 PM
GM's Gravatar Thanks Ray, so you are saying that arguments.thePage gets passed automatically. So, my question then is the name of the variable always thePage? Or could it be something else? And if it is something else how where in the code is this determined?
# Posted By GM | 7/25/08 4:31 AM
Raymond Camden's Gravatar The variable name is based on what you use in the cfargument tag. If you had cfargument name="myfreakingpage", it would be arguments.myfreakingpage.
# Posted By Raymond Camden | 7/28/08 9:08 PM
GM's Gravatar So, Ray sorry for being so dense on this. You mean the cfargument tag name attribute that you are passing to the onRquest method correct?
# Posted By GM | 7/29/08 7:07 AM
Raymond Camden's Gravatar Right - the argument names are up to you.
# Posted By Raymond Camden | 7/29/08 7:11 AM
Sasa's Gravatar If You dont want to deal with argument name you can also use

<cfif listLast(CGI.CF_TEMPLATE_PATH, ".") is "cfc">

I am using this in my Application.cfc and its working. I use this becouse listlast(arguments.thePage,".") in onRequestStart returned error.
# Posted By Sasa | 10/7/08 5:45 AM
Steve's Gravatar Ray, I am having a similar problem related to this topic. However, I'm not using the onRequest/onRequestStart and there is no application.cfc.

When I load my grid page, I get a popup with this error:

Error parsing JSON response: <wddxPacket version='1.0'><header/><data><struct><var name='TOTALROWCOUNT'><number>3.0</number></var><var name='QUERY'><recordset rowCount='1' fieldNames='ID,LOGINID,LOGINPW,LOGINNAME,LOGINLEVEL' type='coldfusion.sql.QueryTable'><field name='ID'><number>3.0</number></field><field name='LOGINID'><string>jaime</string></field><field name='LOGINPW'><string>xXxX</string></field><field name='LOGINNAME'><string>Jaime</string></field><field name='LOGINLEVEL'><string>Admin</string></field></recordset></var></struct></data></wddxPacket> [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]

After clicking Ok, I get this popup:

CFGRID: Response is empty [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]

Now, my dilemma is that I'm on a shared hosting environment and apparently the debugging is turned off. I've tried adding "?cfdebug" to the query string to no avail.

Now, if I perform a cfdump on the CFC using cfinvoke, I show this:

struct
QUERY    
query
   ID    LOGINID    LOGINLEVEL    LOGINNAME    LOGINPW
1    3    jaime    Admin    Jaime    XxXx
2    2    liz    Admin    Liz    XxXx
3    1    steve    Admin    Steve Fister    XxXx
4    [empty string]    [empty string]    [empty string]    [empty string]    [empty string]
5    [empty string]    [empty string]    [empty string]    [empty string]    [empty string]
TOTALROWCOUNT    3

I don't know if this is the problem, but it looks like there are two rows of empty strings and I have absolutely no idea where they are coming from! Checking the db table, there are indeed only 3 rows in the table.

Any ideas? Thanks!
# Posted By Steve | 3/18/09 5:57 PM
Steve's Gravatar Actually, the extra rows issue I have just figured out...they are there as placeholders from the setting of pageSize attribute in cfgrid. Anyhow, still not sure what's wrong with the JSON....

Thanks.

Steve
# Posted By Steve | 3/18/09 6:00 PM
Raymond Camden's Gravatar Notice the XML. It is WDDX. How are you doing your binding? You want to ensure returnformat=json is in the url.
# Posted By Raymond Camden | 3/19/09 9:43 PM
Meenakshi's Gravatar Ray, I am having a similar problem as steve mentioned earlier. I am using onRequestEnd and application.cfc.

When I load my grid page, I get a popup with this error:

Error parsing JSON response: {Total rows:25.... [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]

After clicking Ok, I get this popup:

CFGRID: Response is empty [Enable debugging by adding 'cfdebug' to your URL parameters to see more information]

My CFGRID looks likes this:
<cfgrid format="html" name="employeeGrid" pagesize=11
   stripeRows=true stripeRowColor="gray" bind="url:employeeService.cfc?method=getData&page={cfgridpage}&pagesize={cfgridpagesize}&gridsortcolumn={cfgridsortcolumn}&gridsortdirection={cfgridsortdirection}&returnFormat=json"
   delete="yes" selectmode="edit"
   onchange="cfc:employeeService.editData({cfgridaction},{cfgridrow},{cfgridchanged})">
   
      <cfgridcolumn name="UserID" display=true header="Employee ID"/>
      <cfgridcolumn name="FName" display=true header="First Name"/>
      <cfgridcolumn name="LName" display=true header="Last Name"/>
      <cfgridcolumn name="email" display=true header="Email" />

</cfgrid>

and my employeeService.cfc has this
<cfcomponent displayname="employeeService.cfc" output="false">

<cffunction name="getData" access="remote" output="false" >

   <cfargument name="page">
   <cfargument name="pageSize">
   <cfargument name="gridsortcolumn" default="">
   <cfargument name="gridsortdirection" default="">
   
   <cfquery name="team" datasource="CMS">
   
      SELECT UserID, FName, LName, email
      FROM UserAccounts
      <cfif gridsortcolumn neq "" or gridsortdirection neq "">
      order by #gridsortcolumn# #gridsortdirection#
      </cfif>
   
   </cfquery>
   
   <cfreturn QueryConvertForGrid(team, page, pageSize)>
   
</cffunction>
</cfcomponent>
# Posted By Meenakshi | 4/8/09 10:57 AM
Raymond Camden's Gravatar What does your response look like? Use Firebug to see what you are getting.

Check to ensure CF Debugging is turned off.
# Posted By Raymond Camden | 4/8/09 10:59 AM
Raymond Camden's Gravatar Meenakshi pinged me via email with a screen shot of the error. THe error was a CF error. That means your server side code is throwing an error. The best thing to do is use Firebug's "Open request in new tab" option. This will let you run the page in a new tab and give you a better idea of the error CF is throwing.
# Posted By Raymond Camden | 4/8/09 11:15 AM
Tom McNeer's Gravatar I know this seems insane, because I swear I've used this workaround before. But it's not working now.

I have a simple "Hello World"-type Flex page for testing. It calls a CFC which returns the string "Hello."

When the CFC resides underneath the following Application.cfc, there's an error because the OnRequest method still runs.

Naturally, when I completely comment out the OnRequest method, it works fine. The code in OnRequestStart just isn't deleting OnRequest, for some reason.

Here's the entire Appliation.cfc:

<cfcomponent >
   <cfset this.name = "fred" />
   
   <cffunction name="onRequestStart">
      <cfargument name = "targetPage" type="String" required="true" />
      <!--- ensure CFC / Web Service / Flex Remoting calls are not intercepted --->
      <cfif listlast(arguments.targetPage,".") is "cfc">
         <cfset StructDelete(this, "onRequest") />
         <cfset StructDelete(variables,"onRequest")/>
      </cfif>
   </cffunction>

   <cffunction name="onRequest">
      <cfargument name = "targetPage" type="String" required="true" />
      <cfinclude template = "#Arguments.targetPage#" />
   </cffunction>
   
</cfcomponent>
# Posted By Tom McNeer | 4/21/09 3:00 PM
Raymond Camden's Gravatar Have you tried logging in onRequestStart? It may help debug the issue.
# Posted By Raymond Camden | 4/22/09 3:37 PM
Jake's Gravatar Thank you Ray, this was driving me insane!
# Posted By Jake | 5/5/09 1:11 AM