I have a cfc function which is called via ajax. It accepts a merchant code (either a single code or comma-delimited list of codes), performs some checks and I/O, then returns a flag.
NOTE: We have enabled the CFAdmin setting "prefix JSON with '//'" enabled for security reasons, which seems to be the root of the problem here.
CFC FUNCTION:
There are only two possible returns from this function: A string (e.g. "qweqweqwe"), or "1".
The string is returned within the loop when an invalid merchant_code
is encountered.
"1" is returned after the loop as an indication of success of the entire process.
<cffunction name="createCategoryMerchant" access="remote" returntype="any" returnFormat="JSON">
<cfargument name="category_id" required="true" type="numeric"/>
<cfargument name="merchant_code" required="true" type="any" default="" hint="expect list of merchant codes"/>
<cfset var qChk = 0 />
<cfset var qIns = 0 />
<cfset var vItem = "">
<cfloop list="#arguments.merchant_code#" index="item">
<!--- does merchant exist? --->
<cfquery name="qChk" datasource="#DSN#">
select id from merchant
where merchant_num = <cfqueryparam value="#item#" cfsqltype="cf_sql_varchar" />
</cfquery>
<cfif not qChk.recordcount>
<cfreturn merchant_code> <!--- return bad code, e.g. "qweqweqwe" --->
<cfbreak>
</cfif>
<!--- Has the merchant already been assigned to this category? --->
<cfquery name="qChk" datasource="#DSN#">
select unique_id
from category_merchant
where category_id = <cfqueryparam value="#arguments.category_id#" cfsqltype="cf_sql_integer" />
and merchant_code = <cfqueryparam value="#item#" cfsqltype="cf_sql_varchar" />
</cfquery>
<cfif qChk.recordcount>
<cfcontinue> <!--- silently accept and bail out, even though already exists --->
</cfif>
<!--- insert record if code is legit --->
<cfquery name="qIns" datasource="#DSN#">
insert into category_merchant (category_id, merchant_code)
values (
<cfqueryparam value="#arguments.category_id#" cfsqltype="cf_sql_integer" />,
<cfqueryparam value="#UCASE(item)#" cfsqltype="cf_sql_varchar" />
)
</cfquery>
</cfloop>
<cfreturn 1>
</cffunction>
AJAX:
In the code below, I have included two different ajax call options which I have tried, and each produces different results as noted in the code comments.
$('.btnAddMerchant').on('click',function(e){
var clickedID = $(this).attr("id");
var category_id = clickedID.split("_")[1];
var merchant_code = $('#merchant_code').val();
merchant_code = merchant_code.replace(/\s/g,'');
$('.res').empty().hide;
if(merchant_code.length == 0){
$('#resAdd').show().html('Enter merchant code');
}else{
// OPTION 1: Note I have used "dataFilter" to handle the "//" prefixed JSON
$.ajax({
type:"POST",
url: '/system.cfc?method=createCategoryMerchant',
data: {category_id:category_id,merchant_code:merchant_code},
dataFilter: function(data, type) {return data.substr(2)},
dataType: 'json',
cache:false,
success: function(res) {
alert(res); // This only fires for INVALID codes, i.e. if the cfc returns a string such as "qweqweqwe". Doesn't fire for a single numeric return, e.g. "1"
}
});
// OPTION 2:
$.getJSON("/system.cfc?method=createCategoryMerchant&returnformat=json",{"category_id":category_id,"merchant_code":merchant_code},function(res,code){
alert(res); // This only fires if the code is VALID, i.e. the CFC returns "1". It does not fire if the invalid code "qweqweqwe" is returned
});
}
});
NOTE ALSO: Only the invalid code returns with the "//" prefix. If a "1" is return, this is not prefixed.
If I disable the CFAdmin setting "prefix JSON with '//'", then all the problems disappear. I would prefer to use ajax option 1 above, but need to know why it apparently just silently fails to process the returned flag "1" for valid data.
EDIT
The problem may simply be that the dataFilter attribute in option 1 is working with a returned value that is not prefixed by "//". Then why is it that the "1" is not returned with the "//" prefix, whereas "qweqweqw" DOES have the prefix?
I've resolved this using:
This seems to manually add the "//" prefix to the "1". Not sure why it was absent in the first place.