Copy link to clipboard
Copied
I have following code to get an array from jQuery to pass MS SQL Server stored procedure to update my tables.
Is it the right way to access array from passing jQuery function?
Your help and information is great appreciated,
Regards,
Iccsi,
<cffunction name="MyFunction" access="remote">
<cfargument name="MyData" type="any" required="true">
<cfif isJSON(arguments.MyData)>
<cfset arguments.MyData = deserializeJSON(arguments.MyData)>
</cfif>
<cfstoredproc procedure = "MySP">
<cfprocparam value = "#arguments.MyData[1]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[2]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[3]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[4]#" CFSQLTYPE = "cf_sql_varchar">
<cfprocparam value = "#arguments.MyData[5]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[6]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[7]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[8]#" CFSQLTYPE = "CF_SQL_LONGVARCHAR">
<cfprocparam value = "#arguments.MyData[9]#" CFSQLTYPE = "CF_SQL_LONGVARCHAR">
<cfprocparam value = "#arguments.MyData[10]#" CFSQLTYPE = "cf_sql_date">
<cfprocparam value = "#arguments.MyData[11]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[12]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[13]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[14]#" CFSQLTYPE = "cf_sql_varchar">
<cfprocparam value = "#arguments.MyData[15]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[16]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[17]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[18]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[19]#" CFSQLTYPE = "cf_sql_numeric">
<cfprocparam value = "#arguments.MyData[20]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[21]#" CFSQLTYPE = "cf_sql_date">
<cfprocparam value = "#arguments.MyData[22]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[23]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#arguments.MyData[24]#" CFSQLTYPE = "cf_sql_integer">
</cfstoredproc>
</cffunction>
Further remarks.
(1) The suggestion "MyServer.cfc?method=MyFunction" implies type: "GET".
(2) The JQuery line
data: { argumentCollection: JSON.stringify([$("#txtField1").val(), etc])} implies
<cffunction name="MyFunction" access="remote">
<cfargument name="argumentCollection" type="any" required="true">
</cffunction>
Copy link to clipboard
Copied
I could very well be wrong, but I don't believe it's recommended to replace values of variables in the arguments scope. Instead of
<cfset arguments.MyData = deserializeJSON(arguments.MyData)>
I would maybe do
<cfset local.MyData = deserializeJSON(arguments.MyData)>
Then use local.MyData instead of arguments.MyData in all of your subsequent code. That way the original argument is preserved (in case you find the need to use it down the road).
I'm also a bit uncomfortable assuming that the array coming from your AJAX request is valid and all values are in the correct order. It very well might be that your front-end code assembles that array perfectly, but I wouldn't count on that always being the case. You need to do some validation to make sure that each value in the array is present and not null (or empty), and is the correct type. You might consider submitting a JSON object (key/value pairs) instead of an array, as that will be deserialized into a ColdFusion struct. You could then refer to each value in the struct by keyname instead of array position (so the order of values in the JSON object would not matter), and validating each key/value pair might be easier than validating the array.
-Carl V.
Copy link to clipboard
Copied
One more remark, in addition to what Carl has said. The code assumes an array, so you must test for its existence beforehand.
<cffunction name="MyFunction" access="remote">
<cfargument name="MyData" type="any" required="true">
<cfset var thisData = arguments.MyData>
<cfif isJSON(arguments.MyData)>
<cfset thisData = deserializeJSON(arguments.MyData)>
</cfif>
<cfif isArray(thisData)>
<cfstoredproc procedure = "MySP">
<cfprocparam value = "#thisData[1]#" CFSQLTYPE = "cf_sql_integer">
<cfprocparam value = "#thisData[2]#" CFSQLTYPE = "cf_sql_integer">
<!--- etc.--->
<cfelse>
<!--- What to do if there is no array--->
</cfif>
Copy link to clipboard
Copied
Thanks for the information and help,
I got WDDX packet parse error at line 1 column 1 content is not allowed in prolog...
when I send the array to the cffunction.
I use CFoutput, but it does not show the data I sent.
It seems that CF does not recognize the array sent from my client from jQuery.
Thanks again for helping and information,
Regards,
Iccsi,
Copy link to clipboard
Copied
It sounds like ColdFusion doesn't realize that the data being sent is JSON, and is assuming it is WDDX-wrapped XML.
-Carl V.
Copy link to clipboard
Copied
Here is my jQuery code,
Thanks again,
Regards,
Iccsi,
jQuery.ajax({
url: "MyServer.cfc",
data: {
method: 'MyMethod',
argumentCollection: JSON.stringify([jQuery("#txtField1").val(),
jQuery("#lstField2").val(),
jQuery("#lstField3").val(),
jQuery("#txtField4").val(),
jQuery("#lstField5").val(),
jQuery("#lstField6").val(),
jQuery("#lstField6").val(),
jQuery("#txtField7").val(),
jQuery("#txtField8").val(),
jQuery("#dtpField9").val(),
jQuery("#lstField10").val(),
jQuery("#lstField11").val(),
jQuery("#lstField12").val(),
jQuery("#txtField13").val(),
jQuery("#lstField14").val(),
jQuery("#lstField15").val(),
jQuery("#lstField16").val(),
jQuery("#lstField17").val(),
jQuery("#txtField18").val(),
jQuery("#lstField19").val(),
jQuery("#dtpField20").val(),
jQuery("#lstField21").val(),
jQuery("#lstField22").val(),
jQuery("#lstField23").val()
]
)
},
type: "POST",
success: function(data)
{
alert(" Data update completed");
}
});
Copy link to clipboard
Copied
Yeah, I think you need to restructure that jQuery.ajax() call (take another look at the jQuery api docs). Take method out of the "data" and append it to the URL as "MyServer.cfc?method=MyMethod".
Also, what, exactly does the JSON data look like coming out of the browser (again - use your developer tools or a sniffer and paste the result in your reply)?
You might have a nested object structure being built. You're creating an object with an "argumentCollection" property (key), but you don't reference the argumentCollection key in your ColdFusion CFC. I think you should be able to remove that and just do:
data: JSON.stringify([jQuery("#txtField1").val(),
jQuery("#lstField2").val(),
jQuery("#lstField3").val(),
jQuery("#txtField4").val(),
jQuery("#lstField5").val(),
jQuery("#lstField6").val(),
jQuery("#lstField6").val(),
jQuery("#txtField7").val(),
jQuery("#txtField8").val(),
jQuery("#dtpField9").val(),
jQuery("#lstField10").val(),
jQuery("#lstField11").val(),
jQuery("#lstField12").val(),
jQuery("#txtField13").val(),
jQuery("#lstField14").val(),
jQuery("#lstField15").val(),
jQuery("#lstField16").val(),
jQuery("#lstField17").val(),
jQuery("#txtField18").val(),
jQuery("#lstField19").val(),
jQuery("#dtpField20").val(),
jQuery("#lstField21").val(),
jQuery("#lstField22").val(),
jQuery("#lstField23").val()
]
),
I'm assuming all these fields are part of an HTML form, so rather than manually building your array, why not use the jQuery .serializeArray() function to do the work for you? This will build an array of JavaScript objects (key/value pairs), that will deserialize on the ColdFusion side to an array of structs. Then you'd simply have:
data: jQuery( "#myForm" ).serializeArray(),
Then modify your CFC to work with this new arrangement of JSON data.
-Carl V.
Copy link to clipboard
Copied
Also, is "$" reserved in your JavaScript code for something other than jQuery? If not, use the "$" shorthand instead of "jQuery" on all of your selectors. It'll save you a ton of keystrokes.
-Carl V.
Copy link to clipboard
Copied
Something apparently went wrong even before you called the function. Take a step back to where you called myFunction(someArg). What is the nature of the argument that you used? One way to find out is simply to return the argument, like this:
<cffunction name="MyFunction" access="remote">
<cfargument name="MyData" type="any" required="true">
<cfreturn serializeJSON(arguments.MyData)>
</cffunction>
Copy link to clipboard
Copied
Further remarks.
(1) The suggestion "MyServer.cfc?method=MyFunction" implies type: "GET".
(2) The JQuery line
data: { argumentCollection: JSON.stringify([$("#txtField1").val(), etc])} implies
<cffunction name="MyFunction" access="remote">
<cfargument name="argumentCollection" type="any" required="true">
</cffunction>
Copy link to clipboard
Copied
Yup, good points @BKBK.
-Carl V.
Copy link to clipboard
Copied
Thanks a million for the information and help,
Regards,
Iccsi,