11 Replies Latest reply on May 26, 2014 11:34 AM by iccsi

    cffunction array parameter

    iccsi Level 1

      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>

        • 1. Re: cffunction array parameter
          Carl Von Stetten Adobe Community Professional & MVP

          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.

          • 2. Re: cffunction array parameter
            BKBK Adobe Community Professional & MVP

            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>

            • 3. Re: cffunction array parameter
              iccsi Level 1

              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,

              • 4. Re: cffunction array parameter
                Carl Von Stetten Adobe Community Professional & MVP

                It sounds like ColdFusion doesn't realize that the data being sent is JSON, and is assuming it is WDDX-wrapped XML. 

                1. Can you tell which line of your code is causing the error (the WDDX packet parse error line number is probably the line of the incoming data that causes the error, not the line in your code)? 
                2. Can you show the jQuery code that submits the data to ColdFusion (as you might be missing an argument that sets the content type)?
                3. What does the data in your AJAX request look like? (Use your browser's developer tools or a sniffer like Fiddler or Charles to examine the request content)

                -Carl V.

                • 5. Re: cffunction array parameter
                  BKBK Adobe Community Professional & MVP

                  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>

                  • 6. Re: cffunction array parameter
                    iccsi Level 1

                    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");

                                   

                                     

                                  }

                    });

                    • 7. Re: cffunction array parameter
                      Carl Von Stetten Adobe Community Professional & MVP

                      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.

                      • 8. Re: cffunction array parameter
                        Carl Von Stetten Adobe Community Professional & MVP

                        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.

                        • 9. Re: cffunction array parameter
                          BKBK Adobe Community Professional & MVP

                          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>

                          • 10. Re: cffunction array parameter
                            Carl Von Stetten Adobe Community Professional & MVP

                            Yup, good points @BKBK.

                            -Carl V.

                            • 11. Re: cffunction array parameter
                              iccsi Level 1

                              Thanks a million for the information and help,

                               

                              Regards,

                               

                              Iccsi,