Small "gotcha" When Using ColdBox With AJAX Requests

Nothing big, really. However, I did spend part of the morning figuring it out. If you follow me on Twitter, you might've noticed I had to work out a weird problem with ColdBox and jQuery. What was happening was that I had a jQuery plugin working great with CF8, but as soon as I started using it on an app built around ColdBox it stopped working.

The cause of the issues was actually pretty simple. When you create variables in ColdFusion 8 and return them with returnFormat="json", unless you created them in some fancy way the converter will serialize the variable names to upper case. In ColdBox, the opposite happens. Here's an example:

A sample CFC:

<cfcomponent name="myCFC" output="false">

    <cffunction name="myService" access="remote" returntype="struct">
    
        <cfset var result = { myvariable = "test" } />
        
        <cfreturn result />
    
    </cffunction>

</cfcomponent>

Nothing too complicated happening here. We simply create a structure and put a single key in it. When outputting the return value in Firebug, here's what you get depending on if you're using CF8's built-in conversion or ColdBox's renderData():

Vanilla ColdFusion 8:

"MYVARIABLE":"test"

Using ColdBox and renderData():

"myvariable":"test"

Considering JS is case-sensitive, this has a pretty big impact on the way we work with returned values. I honestly don't know what I prefer between both solutions, but either way is fine. As long as we can rely on the fact that it's always lower case (or upper case for vanilla CF8), that's good enough for me. Just make sure you start by checking what's in your response.

Related Blog Entries

Comments
Timothy Farrar's Gravatar Does it maintain case?

your example was
<cfset var result = { myvariable = "test" } />

so if I did
<cfset var result = { myVariable = "test" } />
would it return
myvariable
or
myVariable
# Posted By Timothy Farrar | 4/23/09 3:08 PM
Francois Levesque's Gravatar Hi Timothy,

I'd check just to make sure, but I'm pretty certain that it converts to lower case so you would indeed get myvariable.
# Posted By Francois Levesque | 4/23/09 3:24 PM
Jason Dean's Gravatar Francois, thanks for the tip. I was actually just about to move some methods in just this way. You may have saved me a lot of time.
# Posted By Jason Dean | 4/23/09 4:10 PM
Francois Levesque's Gravatar Glad I could help, Jason :).
# Posted By Francois Levesque | 4/23/09 4:13 PM
JY's Gravatar Yeah, I notice the case difference too when I moved my ajax calls to coldbox. Actually, for me, the coldbox results give me case that matches the case used in my CF8 code. To get struct keys to maintain uppercase like what CF8 returns, I used this workaround: event.renderData("plain", serializeJSON(variable_name))
# Posted By JY | 4/23/09 4:25 PM
Francois Levesque's Gravatar @JY,

You say that CB matched the case that you used to create your variables. How were you creating them?

<cfset result.myVariable = "test" />

or <cfset result[ "myVariable" ] = "test" />

I believe using the second way ensures the serializer will respect your case, both in ColdBox and CF8. The first option, in my tests, is converted to lowercase or uppercase depending on whether it uses ColdBox's renderData() or not (although serializeJSON() should match whatever CF8 returns when returnFormat is set to "json").
# Posted By Francois Levesque | 4/23/09 4:46 PM
JY's Gravatar @Francois,

I was using the first method you wrote above:
<cfset result.myVariable = value>
<cfset event.renderData("JSON", result>

Then, in firebug, the response showed:
{"myVariable":value}

But then, when I changed to use <cfset event.renderData("plain", serializeJSON(result))>,
I got this {"MYVARIABLE":value} in my response.
# Posted By JY | 4/23/09 5:11 PM
Francois Levesque's Gravatar @JY,

That's odd. I understand the second case, but the first one is leaving me puzzled. I guess it was the way I was declaring my variable:

<cfset result = { myVariable = value } />

I'll need to make more tests to get to the bottom of this. Thank!
# Posted By Francois Levesque | 4/23/09 5:19 PM
Ben Nadel's Gravatar Forgive my complete ignorance of ColdBox... but why are you using renderData()? Why not just let the remote methods return JSON using the inherent ColdFusion data serialization?
# Posted By Ben Nadel | 4/23/09 6:43 PM
Francois Levesque's Gravatar @Ben,

ColdBox uses a proxy component to receive remote calls and interact with the event handlers. To take advantage of the framework's features you need to pass through this proxy.

In your event handler (the controller), you retrieve the data from your models, arrange it as needed and use the framework's renderData method to let the proxy know what data to return to the calling page.

I haven't tried other frameworks in depth but I'd assume they'd use a similar technique to reap the benefits of being part of a framework.

For more info: http://ortus.svnrepository.com/coldbox/trac.cgi/wi...

Enjoy!
# Posted By Francois Levesque | 4/23/09 7:58 PM
Ben Nadel's Gravatar @Francois,

Hmm, interesting. I have always thought of remote calls themselves as a sort of proxy to the primary framework to begin with; meaning, the remote call might turn around internally and execute a "real" framework request, then return final data normally.

But, like I said, I have no real experience in this :)

I need to check out the ColdBox framework. Everyone raves about it.
# Posted By Ben Nadel | 4/23/09 8:01 PM
Vaixe's Gravatar Makes sense. Could there be a way to eternally or on-purpose tell JQ that inputs will be and will forever be (in the scope of the CFM page parsed) be in cas or INcase sensitive?
# Posted By Vaixe | 4/23/09 8:09 PM
Francois Levesque's Gravatar @Ben,

I can't really compare it to the other frameworks out there (Model-Glue, Mach-ii, etc), but what caught my attention was the detailed documentation.

There are also plenty of examples and articles written by the community. Jason Dean's series (http://www.12robots.com/index.cfm/ColdBox) comes to mind as a very nice resource :).
# Posted By Francois Levesque | 4/23/09 8:09 PM
Francois Levesque's Gravatar @Vaixe,

That's an interesting notion. jQuery basically receives a JSON string and parses it to reconstruct the variables locally. I don't know if there's a way to intercept this string and manipulate it first, rather than let jQuery parse it using it's built-in deserializer. Worst case, I imagine it would be possible to write a plug-in that would hook into $.ajaxSetup() to recursively rename keys and variables (not values) to lower / upper case.

Food for thought,
# Posted By Francois Levesque | 4/23/09 8:17 PM
Luis Majano's Gravatar Hi Guys,

By default the json plugin translates keys to lowercase by default. This is done this way, so the plugin can work on cf7 since the json methods where not introduced until cf8.

How about adding an argument to the renderdata that can control the case of the outputted JSON data. Maybe something like:

//default lower
renderData(type="JSON",data=struct)
//do upper
renderData(type="JSON:UPPER",data=struct);

Anyways, thanks for the pointer, what do you guys think it should do?
# Posted By Luis Majano | 4/23/09 10:42 PM
Luis Majano's Gravatar We can also maybe have a caseless json type, where case is respected.

Default: lower

renderData(type="JSON", data=struct);
renderData(type="JSON:LOWER", data=struct);
renderData(type="JSON:UPPER", data=struct);
renderData(type="JSON:NOCASE", data=struct);
# Posted By Luis Majano | 4/23/09 10:46 PM
Francois Levesque's Gravatar @Luis,

That would be really awesome! I can really see a benefit to being able to control whether the serialization converts to lower or upper case. That way we'd know for sure what to expect on the javascript side (and we could reuse JS plugins that were written to work with CF8 and uppercase variable names).
# Posted By Francois Levesque | 4/23/09 11:31 PM
JY's Gravatar @Luis,

Besides struct data, I also notice a case difference for query data. If the query I return is directly from a <cfquery> call, the field names are all in uppercase, but if the query is constructed programmatically using queryNew(fieldNames, types), the field names are in the case entered in the fieldNames list.
# Posted By JY | 4/24/09 1:02 AM
Francois Levesque's Gravatar I've made a couple of tests with variable names and ways of defining them, in both ColdBox and ColdFusion.

http://blog.critical-web.com/blog/index.cfm/2009/4...
# Posted By Francois Levesque | 4/24/09 1:23 AM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.3.000. Contact Blog Owner