Polymer Core-Ajax issue - polymer

Not sure what exactly is happening here.
I am using the polymer core-ajax custom element and in IE 10 and 11 I am getting really weird behavior on the response.
It seems like when I console.log(typeof(response)) the response, the response type returns a string instead of an object, so I can't use object notation to get the properties.
The ajax object is explicitly being set with responseType: 'json'
Note see my notes in //** below
Here is my code:
<core-ajax id="restaurantAjax"
auto
url="{{baseApiUrl + 'restaurants'}}"
on-core-response="{{restaurantsLoaded}}"
handleAs="json">
</core-ajax>
this.async(function() {
this.$.restaurantService.findById(e.detail.id, (function(restaurant) {
this.$.viewrestaurant.wines = restaurant.wines;
//** IE complaining unable to get property wines of undefined or null
this.$.viewrestaurant.restaurant = restaurant;
}).bind(this));
});
findById: function(id, callback) {
this.$.xhr.request({
url: this.baseApiUrl + 'restaurants/' + id,
callback: (function(response) {
console.log(typeof(response))
//* IE returning string instead of object
var restaurant = null;
if (response && response.restaurant) {
restaurant = response.restaurant;
}
callback(restaurant);
}).bind(this),
headers: {
"Content-type": "application/x-www-form-urlencoded"
},
responseType: 'json'
});
}
});
Can someone help me out, its happening randomly across the site, not on all Ajax objects,which is weird in itself.
Thanks,
David

Related

Error returning json data while setting up Stripe payment gateway. Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

so I have been struggling with this for a couple of days and need to find a solution. I followed a tutorial on how to setup Stripe payments the code below is where I am getting the error :
var buyBtn = document.getElementById('payButton');
var responseContainer = document.getElementById('paymentResponse');
// Create a Checkout Session with the selected product
var createCheckoutSession = function(stripe) {
return fetch("stripe_charge.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
checkoutSession: 1,
}),
}).then(function(result) {
return result.json(); // JSON PASSED FROM HERE
});
};
// Handle any errors returned from Checkout
var handleResult = function(result) {
if (result.error) {
responseContainer.innerHTML = '<p>' + result.error.message + '</p>';
}
buyBtn.disabled = false;
buyBtn.textContent = 'Buy Now';
};
// Specify Stripe publishable key to initialize Stripe.js
var stripe = Stripe('<?php echo STRIPE_PUBLISHABLE_KEY; ?>');
buyBtn.addEventListener("click", function(evt) {
buyBtn.disabled = true;
buyBtn.textContent = 'Please wait...';
createCheckoutSession().then(function(data) { // TO HERE - ERROR IS HERE
if (data.sessionId) {
stripe.redirectToCheckout({
sessionId: data.sessionId,
}).then(handleResult);
} else {
handleResult(data);
}
});
});
So you can see above where I am trying to return the json and where I am receiving it. I have double checked the value that is being returned and it is as followed:
json result being returned
and here is the error I am getting :
checkout.php:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
From what I can see it seems that somewhere in the return of the data.json(). The data is being changed so that it is not accepted later in the code.
If anyone could help with this or shine some more light on the situation I would greatly appreciate it. I've had a look online loads and can't seem to find anything other than a HTML file is being passed through instead. The issue is that I don't know HOW this is happening even when looking through the debug.
Thanks a lot.
There is a result, yes, but it is not JSON. Your stripe_charge.php request is almost certainly returning an HTML page instead of the JSON you expect. The error is happening when you try to return result.json(). You need to check your network responses and debug your server code.
See here: https://www.codeproject.com/Tips/1239019/Unexpected-token-in-JSON-at-position
It may be cause because you have put your code in a custom folder.
It works for me by just removing the "/" in fetch("/create-checkout-session.php", {method: "POST",})
in the checkout.html.

wp-json API returns 401 on post edit with React and nonce

I am trying to create an admin page in WordPress with React that allows users to manage post content. I have successfully created a delete method in react to work with the API, but I'm having difficulties getting update to work.
// plugin_file.php
add_action('admin_enqueue_scripts', function() {
wp_localize_script('tfw-js', 'wpApiSettings', [
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' )
]);
});
The code above dumps this object near the bottom of my page
<script type='text/javascript'>
/* <![CDATA[ */
var wpApiSettings = {"root":"http:website.com\/wp-
json\/","nonce":"9eb4c99f2c"};
/* ]]> */
</script>
Here is the delete method that works as intended
deletePost(post) {
var _this = this;
this.serverRequest =
axios
.delete(wpApiSettings.root + "wp/v2/posts/" + post.id, {
headers: {'X-WP-Nonce': wpApiSettings.nonce},
})
.then(function(result) {
_this.updatePostList();
})
}
However my update method, that uses the same nonce key as delete returns 401 unauthorized. I am unsure if the using the same key is the correct approach, but admin-ajax.php uses the same nonce key so I am guessing it is.
updatePost(post) {
var _this = this;
this.serverRequest =
axios
.put(wpApiSettings.root + "wp/v2/posts/" + post.id, {
headers: {'X-WP-Nonce':wpApiSettings.nonce},
data : {
title: 'test'
}
})
.then(function(result) {
_this.updatePostList();
})
}
Error that is returned
{"code":"rest_cannot_edit","message":"Sorry, you are not allowed to edit this post.","data":{"status":401}}
I would prefer not to use an additional plugin to manage this.
Thanks!
Update:
I got this to work easily using jQuery. Not that big of a deal for me as I am just trying to learn React. Still curious if anyone can fill me in on why axios does not work with the exact same headers & post data. My current solution:
updatePost(post) {
var _this = this;
jQuery.ajax({
type: "POST",
url: wpApiSettings.root + "wp/v2/posts/" + post.id,
data: {
"title": 'test',
},
beforeSend: function( xhr ) {
xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce);
}
}).done(function(response) {
_this.updatePostList();
})
.fail(function() {
alert( "error" );
});
}
Hey so I have been having the same issues getting this work as well, but after a long day of troubleshooting, the fix to this was actually fairly simple and easy to overlook.
axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
{ headers: {'X-WP-Nonce':wpApiSettings.nonce}},
{ title: 'test' })
should be
axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
{ title: 'test' },
{ headers: {'X-WP-Nonce':wpApiSettings.nonce}})
I can't believe I misssed this, but the headers should be in an object that is always the third parameter of the PUT or POST functions in Axios. If you don't have any data you want to pass as the second parameter you could also use throw an empty string ''.
I didn't realize the parameter positions mattered, but in the Axios documentation, the prototype is axios.put(url[, data[, config]]). I got it figured out with a friend when we realized that we were putting the header object into the request body instead of actually putting it into the header.
Hope this helps!
You have to
axios.defaults.headers.common['X-WP-Nonce'] = wpApiSettings.nonce;
before sending a request. Best practice would be to set it at your constructor.
and always remember to use qs to serialize your object before sending it.

Angular $http service - force not parsing response to JSON

I have a "test.ini" file in my server, contain the following text:
"[ALL_OFF]
[ALL_ON]
"
I'm trying to get this file content via $http service, here is part of my function:
var params = { url: 'test.ini'};
$http(params).then(
function (APIResponse)
{
deferred.resolve(APIResponse.data);
},
function (APIResponse)
{
deferred.reject(APIResponse);
});
This operation got an Angular exception (SyntaxError: Unexpected token A).
I opened the Angular framework file, and I found the exeption:
Because the text file content start with "[" and end with "]", Angular "think" that is a JSON file.
Here is the Angular code (line 7474 in 1.2.23 version):
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
if (isString(data)) {
// strip json vulnerability protection prefix
data = data.replace(PROTECTION_PREFIX, '');
if (JSON_START.test(data) && JSON_END.test(data))
data = fromJson(data);
}
return data;
}],
My question:
How can I force angular to not make this check (if (JSON_START.test(data) && JSON_END.test(data))) and not parse the text response to JSON?
You can override the defaults by this:
$http({
url: '...',
method: 'GET',
transformResponse: [function (data) {
// Do whatever you want!
return data;
}]
});
The function above replaces the default function you have posted for this HTTP request.
Or read this where they wrote "Overriding the Default Transformations Per Request".
You can also force angular to treat the response as plain text and not JSON:
$http({
url: '...',
method: 'GET',
responseType: 'text'
});
This will make sure that Angular doesn't try to auto detect the content type.

FineUploader OnComplete method not firing

So, I'm using FineUploader 3.3 within a MVC 4 application, and this is a very cool plugin, well worth the nominal cost. Now, I just need to get it working correctly.
I'm pretty new to MVC and absolutely new to passing back JSON, so I need some help getting this to work. Here's what I'm using, all within doc.ready.
var manualuploader = $('#files-upload').fineUploader({
request:
{
endpoint: '#Url.Action("UploadFile", "Survey")',
customHeaders: { Accept: 'application/json' },
params: {
//variables are populated outside of this code snippet
surveyInstanceId: (function () { return instance; }),
surveyItemResultId: (function () { return surveyItemResultId; }),
itemId: (function () { return itemId; }),
imageLoopCounter: (function () { return counter++; })
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png', 'bmp']
},
multiple: true,
text: {
uploadButton: '<i class="icon-plus icon-white"></i>Drop or Select Files'
},
callbacks: {
onComplete: function(id, fileName, responseJSON) {
alert("Success: " + responseJSON.success);
if (responseJSON.success) {
$('#files-upload').append('<img src="img/success.jpg" alt="' + fileName + '">');
}
}
}
}
EDIT: I had been using Internet Explorer 9, then switched to Chrome, Firefox and I can upload just fine. What's required for IE9? Validation doesn't work, regardless of browser.
Endpoint fires, and file/parameters are populated, so this is all good! Validation doesn't stop a user from selecting something outside of this list, but I can work with this for the time being. I can successfully save and do what I need to do with my upload, minus getting the OnComplete to fire. Actually, in IE, I get an OPEN/SAVE dialog with what I have currently.
Question: Are the function parameters in onComplete (id, filename, responseJSON) getting populated by the return or on the way out? I'm just confused about this. Does my JSON have to have these parameters in it, and populated?
I don't do this (populate those parameters), and my output method in C# returns JsonResult looking like this, just returning 'success' (if appropriate):
return Json(new { success = true });
Do I need to add more? This line is after the saving takes place, and all I want to do is tell the user all is good or not. Does the success property in my JSON match up with the responseJSON.success?
What am I missing, or have wrong?
Addressing the items in your question:
Regarding restrictions inside of the "select files" dialog, you must also set the acceptFiles validation option. See the validation option section in the readme for more details.
Your validation option property in the wrong place. It should not be under the request property/option. The same is true for your text, multiple, and callbacks options/properties. Also, you are not setting your callbacks correctly for the jQuery plug-in.
The open/save dialog in IE is caused by your server not returning a response with the correct "Content-Type" header. Your response's Content-Type should be "text/plain". See the server-side readme for more details.
Anything your server returns in it's response will be parsed by Fine Uploader using JSON.parse when handling the response client-side. The result of invoking JSON.parse on your server's response will be passed as the responseJSON parameter to your onComplete callback handler. If you want to pass specific information from your server to your client-side code, such as some text you may want to display client-side, the new name of the uploaded file, etc, you can do so by adding appropriate properties to your server response. This data will then be made available to you in your onComplete handler. If you don't have any need for this, you can simply return the "success" response you are currently returning. The server-side readme, which I have linked to, provides more information about all of this.
To clarify what I have said in #2, your code should look like this:
$('#files-upload').fineUploader({
request: {
endpoint: '#Url.Action("UploadFile", "Survey")',
customHeaders: { Accept: 'application/json' },
params: {
//variables are populated outside of this code snippet
surveyInstanceId: (function () { return instance; }),
surveyItemResultId: (function () { return surveyItemResultId; }),
itemId: (function () { return itemId; }),
imageLoopCounter: (function () { return counter++; })
}
},
validation: {
allowedExtensions: ['jpeg', 'jpg', 'gif', 'png', 'bmp']
},
text: {
uploadButton: '<i class="icon-plus icon-white"></i>Drop or Select Files'
}
})
.on('complete', function(event, id, fileName, responseJSON) {
alert("Success: " + responseJSON.success);
if (responseJSON.success) {
$('#files-upload').append('<img src="img/success.jpg" alt="' + fileName + '">');
}
});

Parse JSON from JQuery.ajax success data

I am having trouble getting the contents of JSON object from a JQery.ajax call. My call:
$('#Search').click(function () {
var query = $('#query').valueOf();
$.ajax({
url: '/Products/Search',
type: "POST",
data: query,
dataType: 'application/json; charset=utf-8',
success: function (data) {
alert(data);
for (var x = 0; x < data.length; x++) {
content = data[x].Id;
content += "<br>";
content += data[x].Name;
content += "<br>";
$(content).appendTo("#ProductList");
// updateListing(data[x]);
}
}
});
});
It seems that the JSON object is being returned correctly because "alert(data)" displays the following
[{"Id": "1", "Name": "Shirt"}, {"Id": "2", "Name":"Pants"}]
but when I try displaying the Id or Name to the page using:
content = data[x].Id;
content += "<br>";
content += data[x].Name;
content += "<br>";
it returns "undefined" to the page. What am I doing wrong?
Thanks for the help.
The data is coming back as the string representation of the JSON and you aren't converting it back to a JavaScript object. Set the dataType to just 'json' to have it converted automatically.
I recommend you use:
var returnedData = JSON.parse(response);
to convert the JSON string (if it is just text) to a JavaScript object.
It works fine,
Ex :
$.ajax({
url: "http://localhost:11141/Search/BasicSearchContent?ContentTitle=" + "تهران",
type: 'GET',
cache: false,
success: function(result) {
// alert(jQuery.dataType);
if (result) {
// var dd = JSON.parse(result);
alert(result[0].Id)
}
},
error: function() {
alert("No");
}
});
Finally, you need to use this statement ...
result[0].Whatever
One of the way you can ensure that this type of mistake (using string instead of json) doesn't happen is to see what gets printed in the alert. When you do
alert(data)
if data is a string, it will print everything that is contains. However if you print is json object. you will get the following response in the alert
[object Object]
If this the response then you can be sure that you can use this as an object (json in this case).
Thus, you need to convert your string into json first, before using it by doing this:
JSON.parse(data)
Well... you are about 3/4 of the way there... you already have your JSON as text.
The problem is that you appear to be handling this string as if it was already a JavaScript object with properties relating to the fields that were transmitted.
It isn't... its just a string.
Queries like "content = data[x].Id;" are bound to fail because JavaScript is not finding these properties attached to the string that it is looking at... again, its JUST a string.
You should be able to simply parse the data as JSON through... yup... the parse method of the JSON object.
myResult = JSON.parse(request.responseText);
Now myResult is a javascript object containing the properties that were transmitted through AJAX.
That should allow you to handle it the way you appear to be trying to.
Looks like JSON.parse was added when ECMA5 was added, so anything fairly modern should be able to handle this natively... if you have to handle fossils, you could also try external libraries to handle this, such as jQuery or JSON2.
For the record, this was already answered by Andy E for someone else HERE.
edit - Saw the request for 'official or credible sources', and probably one of the coders that I find the most credible would be John Resig ~ ECMA5 JSON ~ i would have linked to the actual ECMA5 spec regarding native JSON support, but I would rather refer someone to a master like Resig than a dry specification.
Try the jquery each function to walk through your json object:
$.each(data,function(i,j){
content ='<span>'+j[i].Id+'<br />'+j[i].Name+'<br /></span>';
$('#ProductList').append(content);
});
you can use the jQuery parseJSON method:
var Data = $.parseJSON(response);
input type Button
<input type="button" Id="update" value="Update">
I've successfully posted a form with AJAX in perl. After posting the form, controller returns a JSON response as below
$(function() {
$('#Search').click(function() {
var query = $('#query').val();
var update = $('#update').val();
$.ajax({
type: 'POST',
url: '/Products/Search/',
data: {
'insert': update,
'query': address,
},
success: function(res) {
$('#ProductList').empty('');
console.log(res);
json = JSON.parse(res);
for (var i in json) {
var row = $('<tr>');
row.append($('<td id=' + json[i].Id + '>').html(json[i].Id));
row.append($('<td id=' + json[i].Name + '>').html(json[i].Name));
$('</tr>');
$('#ProductList').append(row);
}
},
error: function() {
alert("did not work");
location.reload(true);
}
});
});
});
I'm not sure whats going wrong with your set up. Maybe the server is not setting the headers properly. Not sure. As a long shot, you can try this
$.ajax({
url : url,
dataType : 'json'
})
.done(function(data, statusText, resObject) {
var jsonData = resObject.responseJSON
})
From the jQuery API: with the setting of dataType, If none is specified, jQuery will try to infer it with $.parseJSON() based on the MIME type (the MIME type for JSON text is "application/json") of the response (in 1.4 JSON will yield a JavaScript object).
Or you can set the dataType to json to convert it automatically.
parse and convert it to js object that's it.
success: function(response) {
var content = "";
var jsondata = JSON.parse(response);
for (var x = 0; x < jsonData.length; x++) {
content += jsondata[x].Id;
content += "<br>";
content += jsondata[x].Name;
content += "<br>";
}
$("#ProductList").append(content);
}
Use
dataType: 'json'
In .NET you could also return Json(yourModel) in your action method/API controller.
And parse the returned JSON as follows in the Jquery .ajax:
if you've a complex object: navigate to it directly.
success: function (res) {
$.each(res.YourObject, function (index, element) {
console.log(element.text);
console.log(element.value);
});
});