How to prevent Coldfusion adding decimals to digit-only varchars? - ajax

I'm using Coldfusion8.
I'm receiving an Ajax request with an item number (random 35 charchater string), which I need to write/retrieve to the database.
Problem is, when I'm passing only digits like:
23456
Coldfusion outputs receiving:
23456.0
If the string contains any letters like A12345 it works correctly.
Some code (although this does not show what's not working:
Javascript:
var btn = $(this).find('input'),
putOnRack = btn.jqmData('index'),
form = "",
service = "../services/handler.cfc",
method = "process",
returnformat = "JSON",
targetUrl = "",
formdata = "form_submitted=store_selection&artikelnummer="+putOnRack+"&method="+method+"&returnformat="+returnformat;
// pass to AJAX
ajaxFormSubmit( form, service, formdata, targetUrl, successHandler, "no", "", returnformat, "" );
var ajaxFormSubmit =
function ( form, service, formdata, targetUrl, successHandler, dataHandler, errorHandler, returnformat, type ){
$.ajax({
async: false,
type: type == "" ? "get" : type,
url: service,
data: formdata,
dataType: returnformat,
success: function( objResponse ){},
error: function (jqXHR, XMLHttpRequest, textStatus, errorThrown) {}
In Coldfusion I'm passing this through process, which validates and builds the form server side, then I pass to my database handler which gets a
`LOCAL.form`
object containing all the passed info, so my item number will be in LOCAL.form.artikelnummer
If I output this:
cfdump output="e:\dump.txt" label="catch" var="#LOCAL.form.artikelnummer#">
digit only strings are treated to .0
Question
How can I make sure I end up with varchar and not numbers, when passing a parameter via AJAX to Coldfusion?

You could use NumberFormat(). Example:
NumberFormat('123.0', '99999')// returns '123'
The second parameter is a mask that determines how your number will be displayed.

Use <cfqueryparam ...> within your cfquery block and specify CFSQLType="CF_SQL_INTEGER". This will also prevent SQL injection attacks (p.s. you should never pass raw data from the end user into your database).
Recommended reading:
cfqueryparam (Coldfusion 8)
Secure your ColdFusion application against SQL injection attacks

You can also use the INT function in CF.
int(123.456) <!--- returns 123 --->
INT is like floor (round down) in other languages
See INT()
You'll need to check your result to make sure if it is a number before trying to use either int or numberFormat or you'll get a The value cannot be converted to a number error.
<cfif isNumeric(yourValue)>
<cfset yourValue = int(yourValue)>
</cfif>

Related

HTTP Post method for search/filter failing at client side?

I had an assignment where I need to have a http POST method which takes int start and int end parameters, then searches database and returns all Cities with population property between the mentioned parameters. Note: I have to use my custom routing for the method.
CitiesController:
[Route("api/cities/search")]
public IHttpActionResult PostSearch(int min, int max)
{
var list = db.Cities
.Where(c => c.Population > min && c.Population < max)
.OrderBy(c => c.Population);
return Ok(list);
}
This is the part in script.js where im calling .ajax POST method.
$("#searchForm").submit(function (e) {
e.preventDefault();
if (token) {
headers.Authorization = "Bearer " + token;
};
var min = $("#searchField1").val();
var max = $("#searchField2").val();
var url = host + "api/cities/search";
var sendData = {
"Min": min,
"Max": max
};
$.ajax({
type: "POST",
url: url,
data: sendData
}).done(fillDataSearch)
.fail(function (data, status) {
alert("!");
});
});
Once i click the submit button in this #searchForm, i get 405 STATUS CODE - Method not allowed Here's what it returns:
<Error>
<Message>The request is invalid.</Message>
<MessageDetail>The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Http.IHttpActionResult Get(Int32)' in 'Finalni_Kraci.Controllers.CitiesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.</MessageDetail>
</Error>
Based on this, he's targeting GET method with parameter int id (which i do have), but i do not know why.
I tried debugging, everything seems okay until he skips to .fail part of $.ajax. I tried testing this with postman, if i put values in parameteres it works, but if i try to pass values through body
{
"Min": 50000,
"Max": 300000
}
i get 405 Status code again with message: The requested resource does not support http method 'POST'.
I am not really sure what is the correct way to do it. So far i tried what i provided but i am losing idea of what i am doing wrong. Let me know if i need to provide anything else.
This was a silly mistake, i had to use filter object as a parameter for my server's POST method, not two integers.
This is solved.

ckan datastore_search API with multiple filters

I'm calling this dataset:
http://data.edinburghopendata.info/api/action/datastore_search?resource_id=4cfb5177-d3db-4efc-ac6f-351af75f9f92
with an AJAX call :
var data = {
resource_id: '4cfb5177-d3db-4efc-ac6f-351af75f9f92',
filters: '{"BankTypeNa": "Packaging", "BankTypeNa": "Compost Bins"}',
limit : 4757
};
$.ajax({
url: 'http://data.edinburghopendata.info/api/action/datastore_search',
data: data,
dataType: 'jsonp',
success: function(data) {
markers = data.result.records;
showMarkers();
}
});
which is giving results only for the second filter.
http://data.edinburghopendata.info/api/action/datastore_search?resource_id=4cfb5177-d3db-4efc-ac6f-351af75f9f92&filters={%22BankTypeNa%22:%20%22Packaging%22,%20%22BankTypeNa%22:%20%22Compost%20Bins%22}
Is there a way, or another parameter I could use to get both "Packaging" and "Compost Bins" in my search results?
Would be nice if somebody can prove me wrong, but its not possible. In theory you would just put the two values in an array as the value for the BankTypeNa key, e.g.
filters: '{"BankTypeNa": ["Packaging", "Compost Bins"]}'
But this doesn't work for text columns (an SQL error results). It does work for numeric ones [1]. It would be good to submit an issue on that at github.com/ckan/ckan.
I would use the datastore_search_sql endpoint instead, i.e.
var data = {
"resource_id": "4cfb5177-d3db-4efc-ac6f-351af75f9f92",
"sql": "SELECT * FROM \"4cfb5177-d3db-4efc-ac6f-351af75f9f92\" WHERE \"BankTypeNa\" LIKE 'Packaging' OR \"BankTypeNa\" LIKE 'Compost Bins'",
"limit": 4757
};
[1] CKAN: delete a list of records within the DataStore in a single query

Django-restframework: How to clear/empty a ManyToMany relation with FormData

I'm editing Django user instances via django-rest-framework, it works well, including setting/changing group membership.
But I can't manage to clear/empty the user from all groups.
This works for me on the shell with httpie:
http -j PATCH :8000/api/accounts/user/1/ groups:='[]'
This is what I try within the browser:
var data = new FormData();
data.append('groups', JSON.stringify([])); // not working
$.ajax({
dataType: 'json',
url: '/api/accounts/user/1/',
type: 'PATCH',
processData: false,
contentType: false,
data: data
});
The form data looks like:
------WebKitFormBoundaryJu7QPC8AcBTpWEKJ
Content-Disposition: form-data; name="groups"
[]
The response is:
{"groups": ["Incorrect type. Expected pk value, received unicode."]}
I guess the problem is that FormData cannot transfer raw JSON like httpie.
restframework treats them differently:
def field_from_native(self, data, files, field_name, into):
...
if self.many:
try:
# Form data
value = data.getlist(field_name)
if value == [''] or value == []:
raise KeyError
except AttributeError:
# Non-form data
value = data[field_name]
This custom method makes it work but I still don't like the approach. To clear I append null to the FormData:
data.append('groups', null);
And make it an empty list on the backend:
class FormDataPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
"""
Custom PrimaryKeyRelatedField which allows clearing via form-data using
JS's 'null' as to clearing value.
"""
def field_from_native(self, data, files, field_name, into):
data = dict(data)
if self.many:
if data.get(field_name) == [u'null']:
data[field_name] = []
super(FormDataPrimaryKeyRelatedField, self).field_from_native(data, files, field_name, into)
class UserSerializer(serializers.ModelSerializer):
groups = FormDataPrimaryKeyRelatedField(many=True, source='groups', required=False)

Passing ampersand to ajax with jquery?

I have this ajax call
function addNewRemarksToDataBase(argRemark) {
if (argRemark != '') {
// if not blank
$.ajax({
url: '../AutoComplete.asmx/AddNewRemarks',
type: 'POST',
timeout: 2000,
datatype: 'xml',
cache: false,
data: 'argRemarks=' + argRemark,
success: function (response) {
// update the field that is source of remarks
updateRemarksSource();
},
error: function (response) {
}
});
}
};
The method is defined as
[WebMethod]
public void AddNewRemarks(string argRemarks)
{
BAL.BalFactory.Instance.BAL_Comments.SaveRemarks(argRemarks, Globals.BranchID);
}
The problem is if a user enters something like long & elegant or something like smart & beautiful, something that contains &, I only get the first part before &, long (in the first case), smart (in the second one) (also notice the whitespace!)
I read in jquery ajax documentation that one should set processData to false, because it is something used for querystring or something. I added the
processData: false
but I am still getting the term before the &. I don't want to use encodeURIComponent because it will turn the & to amp; (or something like that). What I need is the full value long & elegant, smart & beautiful that will be saved to the database. How can I do this?
EDIT Doing { argRemarks: argRemark } doesn't helps! The function doesn't event gets called. Running it with firebug, and setting breakpoint in error function, I got this
[Exception... "Component does not have requested interface" nsresult: "0x80004002 (NS_NOINTERFACE)" location: "JS frame :: http://localhost:49903/js/jquery-1.8.1.min.js :: .send :: line 2" data: no]"
UPDATE 2 :
Doing
data: 'argRemarks=' + encodeURIComponent(argRemark)
did the trick. But can anyone help me understand how does this works? I thought it would convert & to & but it didn't? The parameter I am receiving to the method now is just what I wanted, long & elegant, smart & beautiful, doesn't encodeURIComponent() converts special characters?
You do need to encode the argRemark. The easiest way to do this is to let jQuery do the job for you:
data: { argRemarks: argRemark }
This is different than data: 'argRemarks=' + argRemark in that by passing in an object, jQuery assumes that it needs to URL-encode the values of the properties on that object -- while if passing in a string, you are expected to have properly encoded it beforehand.
You have to URL-encode the string first:
data: 'argRemarks=' + encodeURIComponent(argRemark)

Insert to SQL Server database from jquery mobile application using a server side script (coldfusion)

I've built a jQuery mobile app that gets its content from an external SQL server database via JSON and a server side script (ColdFusion CFC) that interfaces with the database. This app has been packaged as a native app using PhoneGap. I need to enable the jQuery mobile app to be able to write back to the external SQL server db.
Im new to mobile development but have several years of server side development using ColdFusion. I am guessing that the best way to do this is for the mobile app to send the results of the submitted form elements to a server side script for processing. I dont want the native app to send this "as a web page" but rather stay in the app to do it (via AJax I assume).
My server side script will be written in ColdFusion and handles input sanitation and database interaction...I just need to figure out what is the best way to submit from my jQuery app to the server side script, but do it while staying inside of my native application.
I'm pretty much doing the same thing. Server side Coldfuison8/MySQL, front end Jquery Mobile (, requireJS) with all forms submits routed through AJAX to avoid reloading a page.
I'm using a generic form submitter in my controller.js, which looks like this:
var ajaxFormSubmit =
function ( form, service, formdata, targetUrl, successHandler, dataHandler, errorHandler ){
$.ajax({
async: false,
type: "post",
url: service,
data: formdata,
dataType: "json",
success: function( objResponse ){
if (objResponse.SUCCESS == true ){
// alert("success!");
// this passes the response object to the success handler
// in case data needs to be ... handled.
dataHandler == "yes" ? successHandler( objResponse ) : successHandler();
} else {
// alert("AJAX failed!");
if ( errorHandler != "" ){
errorHandler();
}
}
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
//alert("something else failed");
showErrors( [["server-request-error", "server_error"]], XMLHttpRequest, textStatus, errorThrown );
}
});
}
I'm returning results as a response object, which will contain Success = True/false, data (if there is any) and Error = error message.
A function call will look like this:
// the form
var form = $(this).closest('form'),
// trigger for cfcase inside my cfc
switcher = form.find('input[name="form_submitted"]').val(),
// which cfc to call
service = "../cfcs/form_handler_abc.cfc",
// the method in your cfc you are calling (validation/commit to database)
method = "process",
returnformat = "JSON",
// not using
targetUrl = "",
// serialized form plus any value you need to pass along
formdata = form.serialize()+"&method="+method+"&returnformat="+returnformat,
// specific error routine to run
errorHandler = function(){
// in my case, reset the whole form
cleanUp( $('form:jqmData(search="regular")'), "results" )
},
// inside my success handler I'm switching depending on submitted form
// `response` will be the AJAX object.response = whatever you send back from the server
successHandler = function( response ) {
switch (switcher) {
// form A - this is for a search form handling the results
case "getProducts":
// clean up
$('.ajaxContainer, .pagination').addClass('fade out').remove();
// AJAX data received
var makeUp = response.DATA;
// don't forget to trigger create to enhance all JQM elements you are sending
$('.results').append( makeUp ).trigger('create');
// redraw - will fire JQM updatelayout
$(window).trigger('dimensionchange');
// will set bindings on new elements
bindResults( $('.results').closest('div:jqmData(role="page")') );
break;
case "A":
// do sth else
break;
case "B":
// do sth else
break;
}
};
// now pass all of the above to the ajaxFormsubmit
ajaxFormSubmit( form, service, formdata, targetUrl, successHandler, handleData, errorHandler);
I have a number of CFCs, each with a main cfswitch and cfcase for each submitted form. I have built my backend using this sample. Took a while to get going, but now it's running more or less smooth.
Let me know if you have some questions regarding the above.

Resources