Copy link to clipboard
Copied
I am using CF9 in a windows 64bit environment. I am using AJAX functionality to populate a select list with values depending upon the selection of a radio button. I had this working in CF8, but I had hardcoded the datasource, userid, and password for stored procedure calls within the CFC. In my new hosting environment, this is no longer desirable. I tokenized these values by creating variables in the REQUEST scope; defining them in my Application.cfc file. It appears that a CFC called through an AJAX bind does not receive the REQUEST scope and therefore these variables are unavailable within functions residing in the CFC. Furthermore, it seems that the GetAuthUser() function does not work either. It appears to return an empty string instead of the userID of the current logged in user. I have attempted to kludge this problem by passing these values out of the calling CFM as parameters to the functions contained in the CFC. While this works it has an undesirable side-effect. Previously (when only passing a form variable) clicking on a radio button would immediately populate the select list with the appropriated data based upon the button selected; but now, the nothing happens when the user clicks on a radio button. Then when the users clicks on the select list, it suddenly re-populated. Does anyone know of a resolution to either the timing of populating the select list in this context, or how to get the CFC to recognize the REQUEST scope and the GetAuthUser() function... Thanks
Since I could not make CF9 find the CFC, I moved it to a new directory under the WEBroot. (This may be the source of the problem since it no longer lives under the application.cfc'root directory.)
Well: yes. That's your problem (well: it's enough of a problem I didn't bother reading the rest of your post... they might be more problems after that).
If the request variables are set in an Application.cfc file, and your CFC requests aren't going to call that Application.cfc... how do you expect th
...Copy link to clipboard
Copied
The request scope is inappropriate for what you want to do because the cfc was not part of the page request. You are accessing it afterwards.
For the radio button, what event are you using to call your js?
Copy link to clipboard
Copied
Hang on a sec, Dan: you're a bit quick off the mark there. The AJAX request might not be part of the same request (and accordingly request scope) as the initial page load, but it still makes a request, and still has its own request scope. And if request.dsn - or whatever - is set in onRequestStart, then it will be set for the AJAX requests too. Provided, like, the same Application.cfc is running, of course.
--
Adam
Copy link to clipboard
Copied
Not that I actually know any of this, but, my understanding is that Application.cfm/cfc files have influence when a .cfm page that is part of the application is called by an http request. I don't see how this would happen with a javascript request to a cfc.
There certainly is a request, but I don't think any request variables are being set.
Copy link to clipboard
Copied
An HTTP request is an HTTP request. Neither the web server nor CF distinguish between someone hitting a URL by typing it into the address bar of a browser, or clicking a link, or a frameset loading its frames, or an AJAX request being made. All those things are browser conceits, and the server at the other end is unaware of those details. All the web server (and, by proxy, the CF server) see are requests. There is no difference at all.
--
Adam
Copy link to clipboard
Copied
Ya but,
on an ajax request to a cfc, what exactly is it that inspires Application.cfc, or any other template for that matter, to set a request varialbe?
Copy link to clipboard
Copied
The same thing that causes it in response to a "regular" HTTP request from your browser. HTTP is HTTP.
Dave Watts, CTO, Fig Leaf Software
http://www.figleaf.com/
http://training.figleaf.com/
Copy link to clipboard
Copied
As per above, neither the web server nor CF know (or care) that it's "an AJAX request". It's just a request. Same as any other request. There is nothing inate about an AJAX request that makes it any different from any other HTTP request.
Turn the situation around... what is it about an AJAX request that makes you think it is any different from any other sort of request?
--
Adam
Copy link to clipboard
Copied
Regarding, "Turn the situation around... what is it about an AJAX request that makes you think it is any different from any other sort of request?"
This particular request is not to a .cfm file. That being the case, it is unlikely that an Application.cfm/cfc file will be activated and that's the file that likely sets the variables in the request scope.
Copy link to clipboard
Copied
This particular request is not to a .cfm file. That being the case, it is unlikely that an Application.cfm/cfc file will be activated and that's the file that likely sets the variables in the request scope.
CF doesn't make that distinction. A CF file is a CF file, and any request to a CF file - be it a CFM or a CFC - fires Application.cfc (or .cfm).
--
Adam
Copy link to clipboard
Copied
Calling CFCs causes Application.cfc to be run if it's within the same directory or a parent directory, etc, just like running CFM files. This is why you can break certain features of CFCs by using the onRequest event in your Application.cfc.
Dave Watts, CTO, Fig Leaf Software
http://www.figleaf.com/
http://training.figleaf.com/
Copy link to clipboard
Copied
Here are sub-sets of the three files that inter-relate and with which I have a problem. As stated, originally the CFC lived together with the A_Report.cfm's directory. Since I could not make CF9 find the CFC, I moved it to a new directory under the WEBroot. (This may be the source of the problem since it no longer lives under the application.cfc'root directory.) At any rate in it's new location, I needed to pass all the SESSIONinformation into the functions as well as the results of the GetAuthUser() function sincenone of this information was available withing the functions in the CFC. Originally, I onlyneeded to send the1st parameter of each of these functions since the other informationwas available. Before I added the new parameters, when a user clicked on the one of theradio buttons the drop-down list and establishment name (if applicable) was populated.Now, upon clicking the radio button, nothing happens until the user clicks on the drop-downlist and then suddenly it repopulates itself. The only differences in the code are thelocation of the CFC file, the fact that I tokenized the DB login values instead of havingthem hard-coded, and since SESSION variables were not recoginized, I added the parametersto the bind calls.
Because of security concerns of folks I work for, I have changed a number of names that
relate to the actual purpose of the form and the application from which this stuff is extracted.
If the problem is the location of the CFC file vis-a-vis the application.cfc file, can someone explain how to make CF9 recognise a location other than under the WEB root. I have tried creating a CF mapping, and it originally co-existed with the calling CFM... But alas... It prefered the WEB root.
<!--- Application CFC File -------------------------------------------------------------- --->
<cfcomponent output="false">
<cfset THIS.Name="App">
<cfset THIS.scriptProtect="all">
<cfset THIS.SessionManagement="Yes">
<cfset THIS.ClientManagement="Yes">
<cfset THIS.SetClientCookies="No">
<cferror TYPE="validation" TEMPLATE="/shared/Error_InputFieldValidation.cfm">
<cferror TYPE="EXCEPTION" mailTo="me@home.here" TEMPLATE="/shared/Error_ProgramExceptions.cfm">
<cferror TYPE="REQUEST" mailTo="me@home.here" TEMPLATE="/shared/Error_Request.cfm">
<cffunction name="onRequestStart" returnType="boolean" output="true">
<CFSET REQUEST.ds= "THEDATASOURCE">
<CFSET REQUEST.wusr= "THEPRIMARYUSER">
<CFSET REQUEST.ausr= "THESECONDARYUSER">
<CFSET REQUEST.wpwd= "PrimaryUsersPassword">
<CFSET REQUEST.apwd= "SecondaryUsersPassword">
<cfreturn true>
</cffunction>
</cfcomponent>
<!--- A_Report.CFM ----------------------------------------------------------------------- --->
<CFINCLUDE TEMPLATE="/revpath/Manager_Login.cfm">
<CFINCLUDE TEMPLATE="/shared/FunctionHeader.cfm">
<CFIF NOT isdefined("RptStep")>
<HTML>
<HEAD>
<TITLE>A Report</TITLE>
<LINK type="text/css" rel="stylesheet" media="screen" href="/shared/Appstyle.css">
</HEAD>
<BODY>
<CFOUTPUT>#AppPageHeader("Generate an OSHA 300 Privacy List")#</CFOUTPUT>
<div id="outer">
Just some header Information for the user
</div>
<CFFORM ACTION="A_Report.cfm?#CLIENT.urlToken#" METHOD=POST >
<INPUT type="hidden" NAME="RptTitle_Required">
<INPUT TYPE="hidden" NAME="RptStep" VALUE="View">
<INPUT type="hidden" NAME="firstpass" VALUE="Yes">
<FIELDSET Class="input-form-fieldset">
<LEGEND Class="input-form-legend">SMIS Report Set-up:</LEGEND>
<br/><br/>
<CFOUTPUT>
<LABEL for="batch"><A href="#REQUEST.helppath#/hlpRept-Batch.cfm" target="top">Select Organizations From:</a></label>
</CFOUTPUT>
<CFINPUT TYPE="Radio" Name="usebatch" value="1" CHECKED><B>Batch File</B>
<CFINPUT TYPE="Radio" Name="usebatch" value="0"><B>Access List</B>
<CFINPUT TYPE="Radio" Name="usebatch" value="2"><B>Establishment</B>
<br/><br/>
<LABEL for="orgchoice"><A href="#REQUEST.helppath#/hlpRept-PickOrgs.cfm" target="top">Select Organizations:</a></label>
<CFSELECT NAME="orgchoice" Bind="cfc:CFCs.OrgData.GetOrgChoices({usebatch},'#getauthuser()#','#REQUEST.ds#','#REQUEST.wusr#','#REQUEST.wpwd#')" BindOnLoad="yes" display="OrgName" value="Org_ID" />
<!---
Originally (on the working version of this), the CFC was located in the same directory as this template...
I can't speak for the REQUEST scope values (since I had these hard coded in the CFC), but the getauthuser(),
call returned the correct user ID & now it returns nothing, so I passed it into the CFC as well. I don't
know exactly how it worked, but clicking on one of the radio buttons above always re-populated the
list & the Establishment Name, as well as other stuff (not present in this model).
Now, it is populated on load of form, but when radio button is clicked nothing happens until
the user clicks the drop-down list at which time it re-populates itself.
The original line of code follows:
<CFSELECT NAME="orgchoice" Bind="cfc:OrgData.GetOrgChoices({usebatch})" BindOnLoad="yes" display="OrgName" value="Org_ID" />
--->
<br/><br/>
<LABEL for="ename"><A href="#REQUEST.helppath#/hlpRept-EstabName.cfm" target="top">Establishment Name</a>:</label>
<CFINPUT ID="ename" Class="Input-Box" Type="Text" Size="60" Name="RptTitle" MaxLength="60"
Bind="cfc:CFCs.OrgData.GetEstabName({orgchoice},'#REQUEST.ds#','#REQUEST.wusr#','#REQUEST.wpwd#')"
Required="Yes" Message="The Establishment Name (Organization Name) is required for the Report" /><br/><br/>
<INPUT Class="submit-button" Type=submit Value="Send this Info >>">
</FIELDSET>
</CFFORM>
</body>
</html>
<CFELSEIF #RptStep# is "View">
<!--- More code::: irrelevent to this case --->
</CFIF>
<!--- The CFC file --------------------------------------------------------------------------------------------------- --->
<!---
Here is a portion of the CFC that does not seem to understand REQUEST variables,
and evidently SESSION variables either (I'm assuming that is where getAuthUser() must
get it's information. This file is located under the inetpub\wwwroot\CFCs directory
I couldn't get CF 9 to find it anywhere else
--->
<CFCOMPONENT>
<CFFUNCTION Name="GetOrgChoices" Access="Remote" returnType="Query">
<CFARGUMENT NAME="TypeofChoice" Type="Numeric" Default=1>
<CFARGUMENT NAME="user" Type="String">
<CFARGUMENT NAME="dbds" Type="String">
<CFARGUMENT NAME="dbuser" Type="String">
<CFARGUMENT NAME="dbpwd" Type="String">
<CFIF TypeOfChoice eq 0>
<CFSTOREDPROC PROCEDURE="WEB_Ajax_GetAccessList" DATASOURCE="#dbds#" USERNAME="#dbuser#" PASSWORD="#dbpwd#">
<CFPROCPARAM TYPE="In" MAXLENGTH="12" CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#user#">
<CFPROCRESULT NAME="data">
</CFSTOREDPROC>
<CFELSEIF TypeOfChoice eq 1>
<CFSTOREDPROC PROCEDURE="WEB_Ajax_Get_SManager_Batches" DATASOURCE="#dbds#" USERNAME="#dbuser#" PASSWORD="#dbpwd#">
<CFPROCPARAM TYPE="In" MAXLENGTH="12" CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#user#">
<CFPROCRESULT NAME="data">
</CFSTOREDPROC>
<CFELSEIF TypeOfChoice eq 2>
<CFSTOREDPROC PROCEDURE="WEB_Ajax_Get_Estabs_Drillable" DATASOURCE="#dbds#" USERNAME="#dbuser#" PASSWORD="#dbpwd#">
<CFPROCPARAM TYPE="In" MAXLENGTH="12" CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#user#">
<CFPROCPARAM TYPE="In" MAXLENGTH="13" CFSQLTYPE="CF_SQL_VARCHAR" VALUE="SafetyManager">
<!--- The constant "SafetyManager may be replaced with the function "#GetUserRoles()#" when CF8 is deployed --->
<CFPROCRESULT NAME="data">
</CFSTOREDPROC>
<CFELSE>
<div id="urgent">
Invalid value received for choice of organization list in OSHA 300 Log Report!
</div>
<cfabort>
</CFIF>
<CFRETURN data>
</CFFUNCTION>
<CFFUNCTION Name="GetEstabName" Access="Remote" returnType="String">
<CFARGUMENT NAME="EstablishmentID" Type="String" Default="">
<CFARGUMENT NAME="dbds" Type="String">
<CFARGUMENT NAME="dbuser" Type="String">
<CFARGUMENT NAME="dbpwd" Type="String">
<CFSTOREDPROC PROCEDURE="WEB_Ajax_GetEstabName" DATASOURCE="#dbds#" USERNAME="#dbuser#" PASSWORD="#dbpwd#">
<CFPROCPARAM TYPE="In" MAXLENGTH="11" CFSQLTYPE="CF_SQL_VARCHAR" VALUE="#EstablishmentID#">
<CFPROCRESULT NAME="estabname">
</CFSTOREDPROC>
<CFRETURN #estabname.Estab_Name#>
</CFFUNCTION>
</CFCOMPONENT>
Copy link to clipboard
Copied
By the way... Thank you all who are helping me with this issue!!
Copy link to clipboard
Copied
Since I could not make CF9 find the CFC, I moved it to a new directory under the WEBroot. (This may be the source of the problem since it no longer lives under the application.cfc'root directory.)
Well: yes. That's your problem (well: it's enough of a problem I didn't bother reading the rest of your post... they might be more problems after that).
If the request variables are set in an Application.cfc file, and your CFC requests aren't going to call that Application.cfc... how do you expect the request variables to exist? 😉
What you need to do is to drop an Application.cfc into the dir that the CFC(s) are in that extends the other Application.cfc.
Tell me: if you suspected that was the problem, why didn't you investigate that angle?
--
Adam
Copy link to clipboard
Copied
Quite frankly, Adam, it did not occur to me until I was assembling the code (at the request of someone in this forurm) for the post. I'm still not convinced that this is completely solved since the GetAuthUser() function gets it's info elsewhere (I think), and I would prefer (if at all possible) to have a single application.cfm driving the whole show, not have them scattered about the WEB site. Right now we are going through a significant port moving to a completely new hosting enviromnment, Changing form Windows Server 2003 to 2008R2, SQL Server 2005 to 2008, Cold Fusoion 8 to CF 9, and 32 bit to 64 bit. So I am encountering lots of "little" issues along the way. It would really help if I could find a way to get CF9 to recognize a location of my CFC UNDER or along side of the app's application CFC. But I will be expermenting with this some more today. I'll post tonight whether all is well or not.... Thanks again for the help...
Copy link to clipboard
Copied
Adam & Others, I finally got the CFC to be located in a directory under my application.cfm root and was able to make the code work... Kind-of. In-fact (and this is an egg on my face moment) I discovered that it works exactly as before INCLUDING a problem with IE, that I didn't realize existed. I have tested the code in Chrome, Firefox, and Safari and it works perfectly; that is... when a radio button is clicked, the drop-down list populates with the appropriate values. BUT in IE, nothing happens until the drop down list is clicked, at which time it re-populates the list. Using the code that I referenced above (excluding the passed variables that go beyond the "form" scope) does anyone know how to make IE behave like the other browsers. So my problem with the Session scope has been resolved, but I still have this sort-of klunky behavior exibited by IE and unfortunately, my population is probably 95% IE dependent.
Copy link to clipboard
Copied
It appears that a CFC called through an AJAX bind does not receive the REQUEST scope and therefore these variables are unavailable within functions residing in the CFC.
I can't vouch for the getAuthUser() stuff... never used it. However I can repudiate the assertion above. An AJAX request certainly does have a request scope, and certainly does run onRequestStart(). Is that where you're setting your request-scoped variables?
Can you pls post the calling code, the code being called by the AJAX request, plus the relevant bits of your Application.cfc.
You can verify that your onRequestStart handler is being called by putting a CFLOG entry in it, btw (troubleshooting tip...).
--
Adam