POST with parameters AND content
POST with parameters AND content
GregP
Posts: 500Questions: 10Answers: 0
Working on a RESTful service that wants to ingest a set of parameters in the form of JSON. Imagining I don't use DataTables at all, I simply stringify an object and send it as the POST's content. The server reads in the content and acts accordingly.
However, with DataTables what I'm accustomed to is simply POSTing a set of parameters in the usual way, in the header. If I have additional parameters for custom processing, I use fnServerParams to push my new parameters in.
Unfortunately, what I'm accustomed to isn't what the back end development team wants. What they want is a division of concerns:
- the usual DataTables parameters in the header
- the custom information as the request's content.
DataTables is so deep that the function might already exist for specifying content, but I didn't see it. I wasn't really interested in rewriting the entire Ajax call (I like letting DataTables do its job in a default way wherever possible!), so an additional parameter would be ideal.
sAjaxContent or something. ;)
Thanks!
However, with DataTables what I'm accustomed to is simply POSTing a set of parameters in the usual way, in the header. If I have additional parameters for custom processing, I use fnServerParams to push my new parameters in.
Unfortunately, what I'm accustomed to isn't what the back end development team wants. What they want is a division of concerns:
- the usual DataTables parameters in the header
- the custom information as the request's content.
DataTables is so deep that the function might already exist for specifying content, but I didn't see it. I wasn't really interested in rewriting the entire Ajax call (I like letting DataTables do its job in a default way wherever possible!), so an additional parameter would be ideal.
sAjaxContent or something. ;)
Thanks!
This discussion has been closed.
Replies
I'm not sure I 100% understand I'm afraid. The 'HTTP parameters' sent by POST are the POST request's body. Parameters are not sent in the header (HTTP headers). From Wikipedia:
> The POST request method is designed to request that a web server accepts the data enclosed in the request message's body for storage
Here is an example I've just captured with Wireshark in my local examples:
[code]
POST /datatables/DataTables/examples/server_side/scripts/post.php HTTP/1.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-gb) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-gb
Accept-Encoding: gzip, deflate
Content-Length: 507
Connection: keep-alive
sEcho=2&iColumns=5&sColumns=&iDisplayStart=0&iDisplayLength=10&mDataProp_0=0&mDataProp_1=1&mDataProp_2=2&mDataProp_3=3&mDataProp_4=4&sSearch=&bRegex=false&sSearch_0=&bRegex_0=false&bSearchable_0=true&sSearch_1=&bRegex_1=false&bSearchable_1=true&sSearch_2=&bRegex_2=false&bSearchable_2=true&sSearch_3=&bRegex_3=false&bSearchable_3=true&sSearch_4=&bRegex_4=false&bSearchable_4=true&iSortCol_0=1&sSortDir_0=asc&iSortingCols=1&bSortable_0=true&bSortable_1=true&bSortable_2=true&bSortable_3=true&bSortable_4=true
[/code]
You can see here that the request body has the POST parameters in it, and it is these that are decoded by the server to be the POST variables.
So I'm afraid I don't really understand the different you were getting at for the header and the body. It might be my limited understanding of HTTP though...
Allan
Is there a way to change it so that instead of sending a serialized query string, we just send the parameters as stringified JSON? Then it would include both the DT parameters and my custom ones in a format that doesn't need to be more complex than:
[code]
{
"sEcho" : 2,
"iColumns" : 5,
"etc" : "etc",
"myCustom" : "someValue"
}
[/code]
or even better (though not necessary by any stretch):
[code]
{
"dataTables" : {
"sEcho" : 2,
"iColumns" : 5,
"etc" : "etc"
},
"myCustom" : {
"someKey" : "someValue"
}
}
[/code]
I know in a standard $.ajax() jQuery call (which I believe is really all that DT does in the end!), you can set processData to false (it is true by default); but not sure how to "intercept" this setting using DT as the Ajax abstraction layer.
Sort of :-)
You need to override fnServerData and just pass a string to jQuery's Ajax `data` parameter - something like: `data: JSON.stringify( aoData )` . When jQuery seems a plain string passed in as the data for the Ajax request, it simply uses that as the POST body. If it is passed an array of name / value pairs or an object, it will parameterise it for the body before sending it.
Allan
We're going to send the search data as some stringified JSON:
[code]
data: someJSON, // already stringified
[/code]
But we're going to pass the DataTables parameters through the query string.
Normally you would use GET and then the "data" attribute would be appended as a query string. What I need to do is use POST, which means modifying the url parameter:
[code]
url: urlBase + queryString,
data: someJSON, // already stringified
[/code]
where queryString is the set of serialized dataTables parameters (normally aoData).
Is there a way I can retrieve these parameters in order to append them as a string to the URL? I've done a proof of concept in which I just set "queryString = ?foo=bar&baz=mati"; however, I'm not sure how to get my parameters in order to send them in the URL.
I'm sure there's a getter somewhere, but it's a deep API! I can't find it!
I know how to write a serialization function, but I'd rather use anything that's already available. That failing, I'll write the function.
It's on the tip of my brain...
[code]
"fnServerData": function ( sSource, aoData, fnCallback, oSettings ) {
oSettings.jqXHR = $.ajax( {
"dataType": 'json',
"type": "POST",
"url": sSource+'?'+$.param(aoData),
"data": someJSON,
"success": fnCallback
} );
}
[/code]
Allan
For future readers of the thread, it goes something like this:
1. I have a search form, and I need the contents to be sent to the server during the request for data. In other words, during the dataTables initialization and then whenever a draw is requested.
a) I listen for clicks on a "Search" button.
b) I execute $('#form').serializeArray(); on it, storing the results in the variable "form"
b) I iterate through the form, creating a new object that's available in the application namespace (fcSearch.formData):
[code]
for (var i=0, len=form.length; i < len; i++) {
if (form[i].value != "" && form[i].value != "NaN") {
var value = form[i].value;
if (value.match(/^\d+$/)) {
value = +value;
}
fcSearch.formData[form[i].name] = value;
}
}
[/code]
Quite simply, it only pushes into the new object if there's a reason to (the RESTful service just ignores non-present key-value pairs). Additionally, it runs a regex to convert "numbers stored as strings" into actual numbers. This converts something like:
[code]
[
{
name: "something",
value: "foo"
},
{
name: "somethingElse",
value: "123"
}
]
[/code]
into
[code]
{
"something" : "foo",
"somethingElse" : 123
}
[/code]
2. Inside the fnServerData parameter, I immediately send the aoData object off to convert into a similar format. I send along a string to use as a key for an object within the object (you'll see the example in a second for clarification!) The results are stored in a new object that will also contain the formData.
[code]
"fnServerData": function ( sSource, aoData, fnCallback ) {
var newObj = someConvertFunction(aoData, "dataTableParams");
//etc
[/code]
3. I add the formData object to the new object ( newObj["searchCriteria"] = {} ), which results in a JavaScript object that looks like:
[code]
{
"dataTableParams": {
"sEcho": 2,
"iColumns": 10,
"etc" : "etc"
},
"searchCriteria": {
"searchId": "Placeholder",
"resultSet": "sessionSearch",
"etc" : "etc"
}
}
[/code]
4. Instead of passing aoData into the "data" attribute, I now pass a stringified version of the object. So within fnServerData, I have:
[code]
data: JSON.stringify(newObj);
[/code]