Skip to main content
Participating Frequently
March 15, 2011
Answered

Request Scope & CFC called by Bind

  • March 15, 2011
  • 2 replies
  • 2563 views

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

This topic has been closed for replies.
Correct answer Adam Cameron.

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>


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

2 replies

Inspiring
March 20, 2011

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

Inspiring
March 15, 2011

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?

Inspiring
March 20, 2011

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

rapidrayAuthor
Participating Frequently
March 22, 2011

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/


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>