0

I'm getting an error "transaction_types" is undefined, and having trouble understanding why.

I have application.cfc:

<cffunction name="onRequest" >  
    <cfargument name="targetPage" type="String" required=true/> 
    <cfinclude template="header.cfm"> 
</cffunction>

header.cfm file looks like this (header is called on every file and there is a different subheader depending on the directory the user is in):

<cfinclude template="#GetDirectoryFromPath(Arguments.targetPage)#subheader.cfm" />

The directory I'm having a problem with has two files, index.cfm and subheader.cfm

subheader.cfm, the first line

<cfset transaction_types = ["a", "b", "c"] /> 

part of index.cfm, and I think the issue might be the cflocation, but I'm not sure:

<cfif structKeyExists(url, "something") >
    -- some database work is done here --
    <cflocation url="index.cfm">
</cfif> 

--further down on this page, transaction_types is used 

I set the page up thinking transaction_types will be defined any time directory/index.cfm loads, since the application file always loads header.cfm and subsequently directory/subheader.cfm before directory/index.cfm. Does cflocation bypass this?

James A Mohler
  • 11,060
  • 15
  • 46
  • 72
Patrick Schomburg
  • 2,494
  • 1
  • 18
  • 46
  • I believe you are correct Patrick. I don't think a `cflocation` call will go through the normal request processing. It does not call the `onRequest` method. They have documented that it behaves differently with the `onRequestEnd` method as it does not get called either **BUT** it does call the `onAbort` method instead. From the docs: _When using cfabort, cflocation, or cfcontent tags, the OnAbort method is invoked instead on OnRequestEnd._ The call to `cflocation` also stops processing of the current page. – Miguel-F Jul 14 '20 at 19:53
  • Having said all that I do believe the page you `cflocation` to should go through the normal request processing. So say you use `cflocation` to 'page2.cfm'. I think that page2.cfm will invoke the `onRequest` method but the initial page request is stopped when the `cflocation` tag fires. – Miguel-F Jul 14 '20 at 19:58
  • When the error occurs, what page is being processed - index.cfm or subheader.cfm? – Dan Bracuk Jul 14 '20 at 20:46
  • `part of index.cfm, and I think the issue might be the cflocation...` The `index.cfm` script is cflocating to *itself* ... is that a typo? FWIW, you can test whether cflocation calls OnRequest yourself. Create a separate Application.cfc and implement OnRequest. Inside OnRequest method display some text whenever the method is called, like: `writeOutput("onRequest called");` Create a test cfm page with a cflocation call. Run it and see if "onRequest called" appears at the top of the screen. – SOS Jul 15 '20 at 09:14
  • AFAIK when the `cflocation` tag executes it stops the currently processing request, fires the `onAbort` method of Application.cfc, and then sends a 302 HTTP status code (by default) back to the user's browser. That in turn instructs the browser to make a new request of the URL included with that 302 status message. Which should start the process all over again to the new URL. – Miguel-F Jul 15 '20 at 13:29
  • @SOS It's not a typo, I did it because it's after something that would affect the appearance of subheader.cfm (Although I probably should have just reloaded that part of the page via js) Your test does work, so I'm not sure what the error could be the result of. Another interesting note is the user doesn't actually encounter the error, it triggers onError in Application.cfc, which gets logged and (normally) shows the user an error message. It's being logged but not performing the inside onError. – Patrick Schomburg Jul 15 '20 at 20:43
  • @Miguel-F is it possible something to do with onAbort is the problem? As in, could subheader.cfm being aborted BEFORE index.cfm on the cflocation? – Patrick Schomburg Jul 15 '20 at 20:48
  • I don't think so Patrick but not 100% sure. You will need to test and see. Do you even have an onAbort method in your Application.cfc? I'm not totally sure what you are trying to do here but in general the requests will work like this. The first request comes in and processes. When that request processes the cflocation tag it is terminated and the onAbort method is called (if it exists). The cflocation sends an HTTP 302 response to the user's browser. The user's browser then submits a new request to the URL value of the HTTP 302 response. This is a new request and should flow thru process agan – Miguel-F Jul 16 '20 at 13:14
  • @Miguel-F - true, the new request is what flows through OnRequest. Patrick, from what you descibed, it should work, and the variable is defined in my tests. Suggesting something more is occurring in the real code. Maybe trying and narrow it down to the minimal code that reproduces the error might help pinpoint the problem? – SOS Jul 17 '20 at 02:49

1 Answers1

0

You are including code in OnRequest that is setting variables in variables scope of Application.cfc and then trying to reference in template later.

The variables scope of a cfc in general, including Application.cfc specifically though a special case, does not carry through to the templates that are called as part of the request.

If you need to set transaction_types during Application.cfc OnRequest, in included templates or not, and reference in index.cfm later, then it should be done in scope like request and then referenced later as such.

subheader.cfm

<cfset request.transaction_types = ["a", "b", "c"] />

Then refernece as request.transaction_types in index.cfm code.

Dan Roberts
  • 4,664
  • 3
  • 34
  • 43
  • If I'm reading the post correctly, they are setting `transaction_types` in the subheader.cfm template. Not in Application.cfc. The header.cfm template is being included in Application.cfc which is in turn including subheader.cfm. Since those templates are being `cfinclude`ed I think the variable should be within scope. – Miguel-F Jul 15 '20 at 13:21