Twitter: raymondcamden


Address: Lafayette, LA, USA

Ask a Jedi: Ajax-bound requests and onRequest

03-19-2008 7,417 views ColdFusion 38 Comments

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):

view plain print about
1<cfif listlast(arguments.thePage,".") is "cfc">
2<cfset StructDelete(this, "onRequest") />
3<cfset StructDelete(variables,"onRequest")/>
4</cfif>

38 Comments

  • Commented on 03-19-2008 at 11:13 AM
    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.
  • Commented on 03-19-2008 at 12:26 PM
    BIG BIG Bug! Adobe needs to break out the flyswatter for sure on that one.
  • Michael White #
    Commented on 03-20-2008 at 12:11 PM
    more than a bug, it's a scorpion
  • Don Li #
    Commented on 03-21-2008 at 8:05 PM
    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.
  • Commented on 03-22-2008 at 10:37 AM
    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.
  • Don Li #
    Commented on 03-22-2008 at 1:57 PM
    ok, Thank you, Ray. I'll remove my hesitation and move forward with application.cfc then.

    Don
  • Don Li #
    Commented on 04-01-2008 at 7:30 PM
    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.
  • Commented on 04-02-2008 at 8:27 AM
    That code in APp.cfm would be equivalent to the same code in onRequest.
  • GM #
    Commented on 07-24-2008 at 1:46 PM
    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.
  • Commented on 07-24-2008 at 8:25 PM
    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.
  • GM #
    Commented on 07-25-2008 at 4:31 AM
    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?
  • Commented on 07-28-2008 at 9:08 PM
    The variable name is based on what you use in the cfargument tag. If you had cfargument name="myfreakingpage", it would be arguments.myfreakingpage.
  • GM #
    Commented on 07-29-2008 at 7:07 AM
    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?
  • Commented on 07-29-2008 at 7:11 AM
    Right - the argument names are up to you.
  • Sasa #
    Commented on 10-07-2008 at 5:45 AM
    If You dont want to deal with argument name you can also use

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

    I am using this in my Application.cfc and its working. I use this becouse listlast(arguments.thePage,".") in onRequestStart returned error.
  • Steve #
    Commented on 03-18-2009 at 5:57 PM
    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!
  • Steve #
    Commented on 03-18-2009 at 6:00 PM
    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
  • Commented on 03-19-2009 at 9:43 PM
    Notice the XML. It is WDDX. How are you doing your binding? You want to ensure returnformat=json is in the url.
  • Meenakshi #
    Commented on 04-08-2009 at 10:57 AM
    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>
  • Commented on 04-08-2009 at 10:59 AM
    What does your response look like? Use Firebug to see what you are getting.

    Check to ensure CF Debugging is turned off.
  • Commented on 04-08-2009 at 11:15 AM
    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.
  • Tom McNeer #
    Commented on 04-21-2009 at 3:00 PM
    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>
  • Commented on 04-22-2009 at 3:37 PM
    Have you tried logging in onRequestStart? It may help debug the issue.
  • Jake #
    Commented on 05-05-2009 at 1:11 AM
    Thank you Ray, this was driving me insane!
  • Jon Taylor #
    Commented on 07-05-2009 at 7:12 PM
    Wow .. Thankyou ..may the cf force go with you all .. this was driving me nuts.

    As well as the dreaded "Response is empty" it can show in apache logs as an error: "(63)File name too long"

    If you use the application.cfc heavily then wrap anything in the onRequestStart and onRequest in an if/else check for a cfc request and all is good (for me at least).
  • Commented on 07-16-2009 at 10:25 AM
    Wow, This was about to drive me insane. Thanks Raymond...
  • Ranga #
    Commented on 08-05-2009 at 7:10 PM
    This was driving me nuts whole for the whole day.

    The next day I saw something that drove me in commenting out all the functions of App.cfc and my ajax requests started working. I then figured out that onRequest was the one by uncommenting one by one.

    Anyway this should help in uncommenting onRequest function as well.

    Thanks to Ray and SC.
  • Kelvin #
    Commented on 01-24-2010 at 2:03 PM
    Wow! It's now 2010 and this problem still persists in CF. I have been studying the CF 8 volume 1 book. I practiced the examples on auto-suggest and cfgrid and everything went on smoothly. The next chapter introduced Application.cfc. I created an onRequestStart method which simply includes a header and an onRequestEnd method which includes a footer.

    When I tried to show a friend the cool CF Ajax powered auto-suggest / cfgrid functionality, both of the examples I had earlier created didn't work:-(. After searching for a solution for a while, I decided to go back in time. I commented out everything in the Application.cfc and my auto-suggest and cfgrid examples worked again:-). In the end, I realised the problem was with the onRequestStart and onRequestEnd methods. That's how I finally landed in this forum.

    The solution presented here does not solve my problem since I am not using any argument:

    <cffunction name="onRequestStart" returntype="boolean" output="true" hint="Executed before each page request">
          <!--- Display site header at top of every page --->
          <cfinclude template="header.cfm" />

          <cfreturn true />
       </cffunction>
       
       <cffunction name="onRequestEnd" returntype="void" output="true">

          <cfinclude template="footer.cfm" />
       
       </cffunction>

    So how do I solve this?
  • Commented on 01-24-2010 at 3:48 PM
    Actually this problem is solved in ColdFusion 9.

    Why does the solution not help you though? Your statement "I am not using any argument" doesn't make sense. I noticed your code sample showed a header and footer being included in every request. Is that the problem you are trying to solve? If so, that isn't a bug. You code says "Always include a header and footer." Therefore the fact that your Ajax requests break are entirely your fault. What you can do is sniff the page requested. That is always passed to onRequestStart and End. You haven't defined it, but it's passed. See the docs for these two methods. If you then examine the file requested you can simply NOT include the header/footer if the request ends in .cfc.

    Also - I'd recommend not using onRequestStart/End for layout. I'd use a custom tag for that instead.
  • Kelvin #
    Commented on 01-25-2010 at 2:12 PM
    Hi Ray, sorry but I am still missing out something. (still on chapter 19 in the CF 8 book). I now understand that my Ajax requests break are being caused by the header and footer I am including on every page.

    Actually here is the code of the auto-suggest page I am trying to render (it works when I comment out the header and footer in my Application.cfc):
    <cfform>
       <table align="center" style="background-color:green;">
          <tr>
             <th colspan="2">
                <h3>Find an Art Name</h3>
             </th>
          </tr>
          <tr>
             <td>
                Art Name:
             </td>
             <td>      
                <cfinput
                   type="text"
                   name="artName"
                   autoSuggest="cfc:components/artGateway.getArtForAutoSuggest({cfautosuggestvalue})"
                   size="50"
                   maxLength="100"
                />
             </td>
          </tr>
       </table>
    </cfform>

    You said I can simply not include a header/footer if the request ends in .cfc. In this case the page I am requesting is a .cfm page or are you referring to the component being invoked by the auto-suggest control?

    So it means I can't include a header on such a page simply by using the onRequestStart method?

    I am still to study custom tags. When I get there, I will make use of a custom tag as you recommended.

    Thanks
  • Commented on 01-25-2010 at 4:31 PM
    One quick nit - when you use CFC for binding like that, yo use dot notation. Replace the / with a .

    I'm referring to the CFC you used for binding - because your onRequestStart/End runs all the time, it will try to wrap the CFC output with a header/footer as well.
  • Kelvin #
    Commented on 01-25-2010 at 10:59 PM
    Thanks Ray. Everything is now clear and I have been able to work around the problem as you earlier hinted.
  • etothex23 #
    Commented on 03-24-2010 at 10:17 AM
    When you say this is fixed in CF 9, what is fixed?
    I have a header in the onRequestStart() and a footer in the onRequestEnd(). On one page I am building an ajax directory tool and it is a no go.
    and i have a strange issue:
    <!--- Include the requested ColdFusion template. --->
          <cfif ListLast(TargetPage, "/") NEQ "DirectorySearch.cfm">
             <!---<cfinclude template="#APPLICATION.header#" />--->
          <cfelse>
             <cfinclude template="#APPLICATION.header#" />
          </cfif>
           <!---Return out. --->
    This shows the cfc and the header. which then kills it for the pages without the cfc
  • Commented on 03-24-2010 at 10:22 AM
    What's fixed in onRequest breaking the communication. Your code is working like you coded it. You said, before every request, include this template. Therefore, it's a bug in your code. :) You need to modify onRequestStart to look at the requested page. If it is a CFC, don't do the incude.
  • DanGle neck #
    Commented on 05-31-2011 at 7:25 PM
    Aww'sum Thanks for the answer to my problem. I've been banging my head trying to get ajaxproxy to work for over a week.
  • DanGle neck #
    Commented on 05-31-2011 at 7:35 PM
    This work-around also fixes the "?wsdl" problem I was having with cf8.

    the URL: http://www.site.com/myCFC.cfc?wsdl was not displaying the xml.
  • Jonathan #
    Commented on 07-30-2011 at 2:52 AM
    Hi Ray, I need to include my header & footer on every page. How can I do that (as you suggested not to use cfInclude in onRequestStart) and still work with my CFCs
  • Commented on 07-30-2011 at 8:34 AM
    You could, in onRequestStart, sniff for the file extension of the request and if it is cfm, include your request. Ditto for onRequestEnd. I just don't like doing layout in App.cfc. I'd do it there "hard" way and wrap your CFMs with a layout custom tag. This means adding it to each CFM, but that gives you the most control. I promise if you do the "every cfm" approach in app.cfc, you will find a few CFMs where you don't want it, and that means adding a complex CFIF to your logic.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty