Question

Problem: When requesting the WSDL for a CFC, I get the following error: Variable FORM is undefined. It happens in this line of code, in the OnRequestStart method in application.cfc

<cfif structKeyExists(form,'resetappvars')>
    <cfset OnApplicationStart() />
</cfif>

If I request a specific method, it works fine. I have considered using cfparam to create a default form struct if none exists, but that seems like an ugly hack and I worry it will actually create the form struct in the variables or this scope of the CFC. Maybe this is a legitimate bug as well?

Note: This only happens when I request the WSDL, if I invoke a method directly - the code executes as expected without problems.

Update: Application.cfc code sample - just add any CFC to your app and request it with ?wsdl to see the issue. This has been tested (and failed) on ColdFusion 7 and ColdFusion 8.

<cfcomponent output="false">

    <cffunction name="OnApplicationStart" access="public" returntype="boolean" output="false" hint="Fires when the application is first created.">
        <cfset application.dsn = "my_dsn" />
        <cfreturn true />
    </cffunction>

    <cffunction name="OnRequestStart" access="public" returntype="boolean" output="false" hint="Fires at first part of page processing.">
        <cfargument name="TargetPage" type="string" required="true" />
        <cfif structKeyExists(form,'resetappvars')>
            <cfset OnApplicationStart() />
        </cfif>
        <cfreturn true />
    </cffunction>
</cfcomponent>
Was it helpful?

Solution

This post of Ben Nadel gives detailed list of scopes available for different types of requests.

By reading it you can easily find out that form scope is not available in given context, but url is.

OTHER TIPS

Maybe try adding a:

 <cfif IsDefined("form")>...</cfif>

around the above code?

You could also cfparam the variable you're looking for then just change your logic a little (assuming resetAppVars is a boolean:

<cfparam name="form.resetAppVars" default="false" />
...
<cfif form.resetAppVars>
  <cfset OnApplicationStart() />
</cfif>

Edit: I'm not sure if the above code could be considered a hack, but it seems pretty standard CF, to me.

I've heard it's just a matter of opinion, but it seems to me that it is improper to reference your form scope within a CFC, as there is no guarantee that the form scope will be available when your cfc is invoked and when your method is called. It is better to ensure that any data that needs to be available to the method is provided explicitly to your object. This can be done either by including an argument:

<cfargument name="resetAppVars" type="boolean" required="false" default="false" />

Then you check arguments.resetAppVars, and it is always defined, but defaulted to false.

Or by creating an attribute on your object and creating an explicit set method:

(at the top of your cfc)

<cfset this.resetAppVars = false />


<cffunction name="setResetAppVars" access="public" returnType="void" output="false">
   <cfargument name="flagValue" type="boolean" required="true" />

   <cfset this.resetAppVars = arguments.flagValue />
</cffunction>

In which case you will check against this.resetAppVars. You can also scope this locally using <cfset var resetAppVars = false /> as the declaration, which makes it a private attribute of your object, and is probably proper, so code that invokes the object cannot improperly overwrite this variable with a non-boolean type. In that case, you would simply refer directly to resetAppvars in your test, instead of using this scope.

You could also do this:

<cfif NOT isSoapRequest()>...

and stick your remaining logic inside that chunk.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top