jQuery's .ajaxSend: can't add data dynamically - javascript

I use $(document).ajaxSend(...) to dynamically add data (POST args) to some Ajax requests, when necessary.
Adding data works when some datas have been defined in an $.ajax(...) call. But if no data has been defined in the $.ajax setting, my $.ajaxSend can't add data to the settings.
Here is my $.ajaxSend interceptor:
$(document).ajaxSend(function(e, request, settings) {
if(settings.csrfIntention) {
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
}
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
else if(typeof(settings.data) == 'string') {
settings.data += '&_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
else if(!settings.data._token) {
settings.data._token = requestToken;
}
}
});
And an example of $.ajax call that works:
$.ajax({
url: opts.close.url,
method: 'POST',
data: { foo:'bar' },
csrfIntention: 'ajax_close_ticket',
success: function(data) { ... }
});
The $.ajaxSend works and settings.data is set to:
foo=bar&_token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%22uXV1AeZwm-bZL3KlYER-Dowzzd1QmCmaT6aJFjWLpLY%22%7D
Serverside, I can retrieve the two fields: foo and _token.
Now, if I remove the data object in the $.ajax call, the output of $.ajaxSend seems Ok, too:
_token=%7B%22intention%22%3A%22ajax_close_ticket%22%2C%22hash%22%3A%225cK2WIegwI6u8K_FrxywuauWOo79xvhIcASQrZ9QPZQ%22%7D
Yet, the server don't receive my _token field :(
Another interesting fact: when I have the two fields, the Chromium dev tools under the Network tab displays the two fields under a "Form Data" title. When _token is alone, "Form Data" is replaced by "Request Payload".
Edit: just understood why _token is not interpreted by the server. If no data has been previously set in $.ajax call, jQuery does not add the right Content-Type in HTTP headers, it set it to text/plain instead of application/x-www-form-urlencoded. How can I force jQuery to add this header?
Edit 2: Solution found. Will post an answer to help other people...

I apologize for my bad English
I believe that the solution to his case would be the use of the function "ajaxSetup"
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
};
$.ajaxSetup({
data : {
_token: requestToken
}
});
this way all your orders took the data as the desire

A simpler approach:
var requestToken = {
intention: settings.csrfIntention,
hash: self.tokens[settings.csrfIntention]
}
var myForm = {};
myForm['_token'] = encodeURIComponent(JSON.stringify(requestToken));
In your ajax call:
myForm['foo'] = 'bar';
$.ajax({
url: opts.close.url,
method: 'POST',
data: myForm,
csrfIntention: 'ajax_close_ticket',
success: function(data) { ... }
});
//This sends foo and _token

Finally I answer my question after only 10 minutes...
In HTTP, the form arguments are sent into the request body, under the headers. The header Content-Type should be present to declare the data type. When this header is set to application/x-www-form-urlencoded, the server will understand that you sent a form and will parse the request body as a GET URL (you know, the foo=bar&key=val format).
jQuery adds this header automatically when you set a data object into the $.ajax call. Then it passes the request to the $.ajaxSend callback, which adds its proper fields.
When no data has been provided in request settings, jQuery do not add an unnecessary Content-Type: x-www-form-urlencoded in the request headers. Then, when you append the request body into your $.ajaxSend callback, jQuery do not check the data again and declares the content as text/plain. The server has nothing to do with text/plain so it does not interpret the body data as form fields.
You can obviously force jQuery to change the header to application/x-www-form-urlencoded, let's take the code of my original post :
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
}
Now add the right header:
if(!settings.data) {
settings.data = '_token=' + encodeURIComponent(JSON.stringify(requestToken));
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}

Related

Extracting data from json in JavaScript

I have ajax connection with controller
function changeEmail() {
$.ajax({
...
contentType: "application/json",
dataType: "json",
...
error: function (error) {
var obj = error.responseText;
console.log('Error: ' + obj);
console.log('Obj length: ' + obj.fieldErrors.length);
}
});
}
Which in case of error returns a list of errors in json.
However, he is not able to refer to this list.
https://zapodaj.net/e6354b8c71f4c.png.html
I do not know, for example, how to refer to the first element of a list to the
message
variable
Depending on the content-type response from your server, the default response type is probably text/html or some other incorrect content-type.
You have two ways to fix this.
First, you can set obj = JSON.parse(error.responseText)
or, you can make sure that the server sets the correct content-type on errors as well.

How to send an HTTP request with a header parameter?

I'm very new to javascript and web programming in general and I need some help with this. I have an HTTP request that I need to send through javascript and get need to store the output in a variable. I tried using just the call url:
https://api.fantasydata.net/nfl/v2/JSON/PlayerSeasonStats/2015
But it returns an authentication error because I didn't send my API key and it doesn't show me how to do it just in the URL. The API key is listed as a header and not a paramater and I'm not sure what to do with that. I tried using the XMLHttpRequest() class but I'm not quite sure I understand exactly what it does nor could I get it to work.
The actual HTTP Request
GET https://api.fantasydata.net/nfl/v2/JSON/PlayerSeasonStats/2015 HTTP/1.1
Host: api.fantasydata.net
Ocp-Apim-Subscription-Key: ••••••••••••••••••••••••••••••••
I just need to figure out how to send that request along with the key and how to store the JSON doc it returns as a variable in javascript.
EDIT: This is what I have so far:
function testingAPI(){
var key = "8a1c6a354c884c658ff29a8636fd7c18";
httpGet("https://api.fantasydata.net/nfl/v2/JSON/PlayerSeasonStats/2015",key );
alert(xmlHttp.responseText);
var x = 0;
}
function httpGet(theUrl,key)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.setRequestHeader("Ocp-Apim-Subscription-Key",key);
xmlHttp.send( null );
return xmlHttp.responseText;
}
Thank you!
If it says the API key is listed as a header, more than likely you need to set it in the headers option of your http request. Normally something like this :
headers: {'Authorization': '[your API key]'}
Here is an example from another Question
$http({method: 'GET', url: '[the-target-url]', headers: {
'Authorization': '[your-api-key]'}
});
Edit : Just saw you wanted to store the response in a variable. In this case I would probably just use AJAX. Something like this :
$.ajax({
type : "GET",
url : "[the-target-url]",
beforeSend: function(xhr){xhr.setRequestHeader('Authorization', '[your-api-key]');},
success : function(result) {
//set your variable to the result
},
error : function(result) {
//handle the error
}
});
I got this from this question and I'm at work so I can't test it at the moment but looks solid
Edit 2: Pretty sure you should be able to use this line :
headers: {'Authorization': '[your API key]'},
instead of the beforeSend line in the first edit. This may be simpler for you
With your own Code and a Slight Change withou jQuery,
function testingAPI(){
var key = "8a1c6a354c884c658ff29a8636fd7c18";
var url = "https://api.fantasydata.net/nfl/v2/JSON/PlayerSeasonStats/2015";
console.log(httpGet(url,key));
}
function httpGet(url,key){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", url, false );
xmlHttp.setRequestHeader("Ocp-Apim-Subscription-Key",key);
xmlHttp.send(null);
return xmlHttp.responseText;
}
Thank You
**`
U need to have a
send();
Statement.
That way you can send the request to the site server.
`**

how to send data from one web page to another?

I don't how to ask this question but if their are duplicates send me that. Their are several .php files i have made
content.php, show.php and showFilteredResult.php .
content.php sends the start date and end date to the show.php and it returns the the orderIds which are of that date
$(document).ready(function () {
var srt = $("#cal1Date1").val();
var end = $("#cal1Date2").val();
$.ajax({
url: "http://localhost/show.php",
data: {
srt: srt,
end: end
},
type: "POST",
dataType: "json",
complete: function (response) {
$rtndata = response.responseText;
var dat1a = jQuery.parseJSON($rtndata);
var result = dat1a.OrderID;
console.log(result[0]); // send this result
}
});
});
now I want to send this $result with orderids to showFilteredResult.php where then i can make tables etc.
I'd skip the AJAX and just use request parameters (GET or POST).
cal1Date1 and cal1Date2 are input fields I assume. Wrap them in a form and post the values to a PHP form handler that could handle the lookup and display. No need for the AJAX middle-man here.
Just make a similar Ajax request to showFilteredResult.php I would have them in a separate function.
function showFilteredResult($result){
$.ajax({
url:"http://localhost/showFilteredResult.php",
data: {
result:$result
},
type:"POST",
dataType: "json",
complete:function(response){
$rtndata=response.responseText;
var dat1a=jQuery.parseJSON($rtndata);
var result=dat1a.OrderID;
console.log(result[0]);// do something with the data returned from showFilteredResult.php
}
});
}
and from the request that you have just call that funciton like
... $rtndata=response.responseText;
var dat1a=jQuery.parseJSON($rtndata);
var result=dat1a.OrderID;
console.log(result[0]);// send this result
showFilteredResult(result[0]);
}
});
Instead making another request to server , you have another option to do that. Let's say you get orderId from show.php before sending back , right ? Then you can use this orderId to do what u want such as query which u have written in showFilteredResult.php . then return back to client for final result . In that way you can eliminate the unnecessary http request.

Basic "Raw" Ajax Call

I have a serverside function:
string foo(string input_string);
for example:
foo("bar") returns "baz"
and have wrapped this function into a HTTP server such that:
POST /foo HTTP/1.1
...
bar
will return:
HTTP/1.1 200 OK
...
baz
ie a POST request with the input string as the HTTP Message Body will return the output string as the HTTP Message Body of the 200 OK.
Now in my javascript on the web page I have two functions:
function sendFoo(input_string)
{
??? // should asynchronously start process to POST input_string to server
}
function recvFoo(output_string)
{
...
}
When I call sendFoo I would like the POST to be made asynchronously to the server and later when the response is received I would like recvFoo called (perhaps in another thread or whatever) with the Message Body of the 200 OK.
How do I implement sendFoo above? I am currently using jQuery, but a solution in pure javascript is ok too. (I can also modify the server if need be?)
Solution:
function sendFoo(input_string)
{
$.ajax({ url: "/foo", type: "POST", data: input_string, success: recvFoo });
}
XMLHttpRequest object's open() method allows you to specify the HTTP method while the send() method allows to specify the message body, e.g.
var xhr = ... // obtain XMLHttpRequest object
xhr.open('POST', '/foo'); // HTTP method and requested URL.
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
recvFoo(xhr.responseText); // Will pass 'baz' to recvFoo().
}
};
xhr.send('bar'); // Message body with your function's argument.
No need to fallback to classic JavaScript
$.ajax({
url:"URL of foo...",
type: "POST",
data: "what ever",
success: recvFoo
});
Or the post option:
$.post('The url of foo', {input_string : 'bar'}, recvFoo);
jQuery post will do the job:
$.post('foo.html', {'varname' : 'bar'}, function(data) {
recvFoo(data);
});
Very well laid out question, thanks.

ASP.NET MVC JsonResult return 500

I have this controller method:
public JsonResult List(int number) {
var list = new Dictionary <int, string> ();
list.Add(1, "one");
list.Add(2, "two");
list.Add(3, "three");
var q = (from h in list where h.Key == number select new {
key = h.Key,
value = h.Value
});
return Json(list);
}
On the client side, have this jQuery script:
$("#radio1").click(function() {
$.ajax({
url: "/Home/List",
dataType: "json",
data: {
number: '1'
},
success: function(data) {
alert(data)
},
error: function(xhr) {
alert(xhr.status)
}
});
});
I always get an error code 500. What's the problem?
Thank you
If you saw the actual response, it would probably say
This request has been blocked because
sensitive information could be
disclosed to third party web sites
when this is used in a GET request. To
allow GET requests, set
JsonRequestBehavior to AllowGet.
You'll need to use the overloaded Json constructor to include a JsonRequestBehavior of JsonRequestBehavior.AllowGet such as:
return Json(list, JsonRequestBehavior.AllowGet);
Here's how it looks in your example code (note this also changes your ints to strings or else you'd get another error).
public JsonResult List(int number) {
var list = new Dictionary<string, string>();
list.Add("1", "one");
list.Add("2", "two");
list.Add("3", "three");
var q = (from h in list
where h.Key == number.ToString()
select new {
key = h.Key,
value = h.Value
});
return Json(list, JsonRequestBehavior.AllowGet);
}
While JustinStolle's answer solves your problem, I would pay attention to the error provided from the framework. Unless you have a good reason to want to send your data with the GET method, you should aim to send it with the POST method.
The thing is, when you use the GET method, your parameters gets added to your request url instead of added to the headers/body of your request. This might seem like a tiny difference, but the error hints why it's important. Proxy servers and other potential servers between the sender and the receiver are prone to logging the request url and often ignore the headers and/or body of the request. This information is also often regarded as non important/secret so any data exposed in the url is much less secure by default.
The best practice is then to send your data with the POST method so your data is added to the body instead of the url. Luckily this is easily changed, especially since you're using jquery. You can either use the $.post wrapper or add type: "POST" to your parameters:
$.ajax({
url: "/Home/List",
type: "POST",
dataType: "json",
data: { number: '1' },
success: function (data) { alert(data) },
error: function (xhr) { alert(xhr.status) }
});

Categories