AJAX JSON with ServiceStack - ajax

I have spend over 10 hours trying to figure this out and looking at similar examples from other people but unfortunately I haven't been able to find out what's my problem here.
I have a ServiceStack Webservice setup:
http://example.com/v1/getuser?code=abcd&lastname=doe&format=json
If I run the above via the browser I will get the following:
[{"nameresult":"joe"}]
I am trying to get this via making an ajax call as follow:
var code = $("#code_field").val();
var lastname = $("#lastname_field").val();
$.ajax({
url: "http://example.com/v1/getuser",
type: "POST",
data: JSON.stringify({
code: code,
lastname: lastname,
format: 'json'
}),
contentType: "application/json; charset=utf-8",
success: function (data) {
var returned_data = data;
alert('returned_data=' + returned_data);
},
error: function (xhRequest, ErrorText, thrownError) {
console.log('xhRequest: ' + xhRequest + "\n");
console.log('ErrorText: ' + ErrorText + "\n");
console.log('thrownError: ' + thrownError + "\n");
}
});
When I run the above, I get the following:
returned_data=[object Object]
Does anyone knows how could I get the json result, nameresult=joe? I am assuming that [object Object] contains [{"nameresult":"joe"}] but I am not entirely sure because I cannot see inside the object :(. thanks so much.
LATEST UPDATE - PROBLEM SOLVED!
I figured out the problem I was having. It had to do with ServiceStack and not with the Ajax call. My problems was the following, I hope it helps someone else one day that may face the same issue.
1.- I needed to enable CORS support on ServiceStack in order to allow posting parameters from Ajax:
File: AppHost.cs
//Permit modern browsers (e.g. Firefox) to allow sending of any REST HTTP Method
base.SetConfig(new EndpointHostConfig
{
GlobalResponseHeaders = {
{ "Access-Control-Allow-Origin", "*" },
{ "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" },
{ "Access-Control-Allow-Headers", "Content-Type" },
},
});
Plugins.Add(new CorsFeature());
this.RequestFilters.Add((httpReq, httpRes, requestDto) =>
{
//Handles Request and closes Responses after emitting global HTTP Headers
if (httpReq.HttpMethod == "OPTIONS")
httpRes.EndServiceStackRequest(); //httpExtensions method
// =>after v.3.9.60, => httpRes.EndRequestWithNoContent();
});
2.- My getuser method was in the GET instead of POST. I moved that to the POST and problem solved.
Moved getuser from here: public object Get(...) into here public object Post(...)
Thanks to all for helping me figure this out.

Use console.log to output returned_data by itself:
console.log(returned_data);
This will display the JSON object:
{"nameresult":"joe"}
Your original alert concatenates the string "returned_data=" with the JSON object, and thus the object is converted to a placeholder string "[object Object]" by the browser.
I often put my label in one log, and the object in another:
console.log('returned_data:');
console.log(returned_data);

Related

How-to correctly pass params between Parse Cloud Code and the Client? (httpRequest Example)

I've seen some examples, read the docs and read other question however I'm still not quite sure where to add/properly add params to be passed between Cloud Code and my Client side correctly.
For Instance, Here I am creating a new class from a httpRequest in my Cloud Code
In my Cloud Code main.js
Parse.Cloud.define("POSTfromCloud", function(request, response) {
//runs when Parse.Cloud.run("POSTfromCloud") on the client side is called
Parse.Cloud.httpRequest({
method: "POST",
headers: {
"X-Parse-Application-Id": "[PARSE_APP_ID]",
"X-Parse-REST-API-Key": "[PARSE_REST_ID]",
"Content-Type": "application/json"
},
//adds a new class to my parse data
url: "https://api.parse.com/1/classes/newPOSTfromCloudClass/",
body: {
"newPOSTfromCloudClass": {"key1":"value1","key2":"value2"}
},
success: function (httpResponse) {
console.log(httpResponse.text);
response.success(httpResponse);
},
error:function (httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
response.error(httpResponse.status);
}
}); //end of Parse.Cloud.httpRequest()
});
on my client side
Parse.Cloud.run('POSTfromCloud', {}, {
success: function(result) {
console.log("Posted a new Parse Class from Cloud Code Successfully! :"+ JSON.stringify(result))
},
error: function(error) {
console.log("Oops! Couldn't POST from Cloud Code successfully.. :"+ error)
}
});
}
My Result:
Bam! Got that working correctly. Now lets say I want to make my url one of many parameters passed how do I do this?
As I was asking this I was also tinkering with some things because I coundn't get anything to pass correctly (or it would return as an empty value) so here I have and example on how I can pass parameters into this.
in my cloudcode main.js
Parse.Cloud.define("POSTfromCloud", function(request, response) {
//HERE- make a new instance of 'myValue' for Cloudcode to handle
var myValue = request.params.myValue;
Parse.Cloud.httpRequest({
method: "POST",
....[blah blah]
//AND HERE- placed that here in my body, **note:** you shouldnt store tokens like this, ignore what I named it
body: {
"newPOSTfromCloudClass": {"yourToken":myValue,"key2":"value2"}
},
client side
var myvalue = "I'm The VALUE";
Parse.Cloud.run('POSTfromCloud', {myValue: myvalue}, {
success: function(result) {
Result: this should have passed the param correctly. Again ignore me using the title "yourToken", you shouldn't be storing tokens like that.
This took a while to put together, I hope this can help someone.

Vue.js-resource: http request with api key (Asana)

I'm trying to extract some projects from the Asana api with vue-resource (https://github.com/vuejs/vue-resource), a Vue.js add-on that makes ajax calls simple. I'm using an api key to access Asana, but I can't figure out how to pass the key in the request header using vue-resource.
In jQuery this works, using beforeSend:
$.ajax ({
type: "GET",
url: "https://app.asana.com/api/1.0/projects?opt_fields=name,notes",
dataType: 'json',
beforeSend: function(xhr) {
xhr.setRequestHeader("Authorization", "Basic " + "XXXXXX");
},
success: function (data){
// console.log(data);
}
});
Where XXXXXX is the Asana api key + ':' converted with btoa(). https://asana.com/developers/documentation/getting-started/authentication
Without needing to authenticate, the Vue instance should be fine with a simple request in the ready function:
new Vue({
el: '#asana_projects',
data: {
projects : []
},
ready: function() {
this.$http.get('https://app.asana.com/api/1.0/projects?opt_fields=name,notes', function (projects) {
this.$set('projects', projects); // $set sets a property even if it's not declared
});
},
methods: {
// functions here
}
});
This, of course, returns a 401 (Unauthorized), since there is no api key in there.
On the vue-resource github page there is also a beforeSend option for the request, but even though it is described right there I can't seem to figure out the correct syntax for it.
I have tried
this.$http.get( ... ).beforeSend( ... );
// -> "beforeSend is not a function", and
this.$http.get(URL, {beforeSend: function (req, opt) { ... }, function(projects) { //set... });
// -> runs the function but req and opt are undefined (of course)
I realize I'm being less than clever as I fail to understand a syntax that is right there in the documentation, but any and all help would be much appreciated!
Any takers?
Perhaps I'm missing some subtlety but can't you use the options parameter to the $get call to specify the header? From the docs: https://github.com/vuejs/vue-resource#methods
Methods
Vue.http.get(url, [data], [success], [options])
[...]
Options
[...]
headers - Object - Headers object to be sent as HTTP request headers
[...]
So for instance:
this.$http.get(
'https://app.asana.com/api/1.0/projects?opt_fields=name,notes',
function (projects) {
this.$set('projects', projects); // $set sets a property even if it's not declared
},
{
headers: {
"Authorization": "Basic " + "XXXXXX"
}
}
);
You can also configure the auth token for all calls like this:
Vue.http.options.root = '/root';
Vue.http.headers.common['Authorization'] = 'Basic YXBpOnBhc3N3b3Jk';
See the docs

Unable to work Cloud Code httpRequest HEAD method

Not sure if I'm doing this wrong but I want to make a cloud code httpRequest to validate URLs. I wanted to use the HEAD method and save on some data traffic but specifying HEAD seems to do exactly the same as a GET... seems like I'm getting the full body as well.
Parse.Cloud.define('validateURL', function(request, response) {
var params = request.params;
var url = params.url;
Parse.Cloud.httpRequest({
url: url,
followRedirects: true,
method: 'HEAD'
}).then(function(httpResponse) {
// Redundant
var httpObject = {
buffer: httpResponse.buffer,
cookies: httpResponse.cookies,
data: httpResponse.data,
headers: httpResponse.headers,
status: httpResponse.status,
text: httpResponse.text
};
response.success(httpObject);
}, function(error) {
response.error(error.message);
});
});
I guess the question is, is this my problem or Parse.com's problem (or both or neither?)
Your httpRequest looks correct. You might want to file a bug report.

406 Error when returning JSON object – Unexpected content

A few colleagues and I have a problem whereby the response from an ajax call returns some unexpected content. Rather than getting a simple JSON object back with various properties, the value of result.responseText is the HTML markup of a generic 406 status error page, saying the MIME type is not accepted by the browser.
The call is made like so:
$.ajax({
url: '/promociones/cincogratis/canjear-codigo-promocional',
type: this.method,
data: $(this).serialize(),
success: function (result) {
$('.promotion_banner .loader').hide();
$('.promotion_banner').html(result);
},
error: function (result) {
var obj = result.responseText;
if (obj.isRedirect) {
document.location = obj.redirectUrl;
}
else {
$('.promotion_banner .loader').hide();
$(".error-wrapper").removeClass("hidden");
var generic_error = document.getElementById('generic_error').value;
$(".error-wrapper p").html(generic_error);
}
},
beforeSend: function() {
$('.promotion_banner .loader').show();
}
});
The controller response to the call is like so:
Response.StatusCode = (int)HttpStatusCode.NotAcceptable; // 406
return Json(new { errorMessage = LocalErrorMessages.Website_Promotions_FreeFiver_General_Problem, isRedirect = false } );
We would expect result.responseText to contain key values for errorMessage and isRedirect, but they’re not there.
It’s worth pointing out that this code is multi-tenanted, shared by the current application and another one, where it works absolutely fine.
We’ve tried:
- Configuring IIS to show detailed error responses rather than a custom page for more detail – gives us nothing extra towards solving the problem.
- Allowing all response content types to the call
- Changing the culture of our site (which is currently es-ES)
- Various web.config tweaks
Has anyone ever had this problem?
Simplify your request. Maybe something like:
$.ajax({
url: '/promociones/cincogratis/canjear-codigo-promocional',
type: 'GET',
data: {foo:'bar', one:'two'},
dataType: 'json',
success: function (result) {
console.dir(result);
},
error: function (xhr) {
console.dir(xhr)
}
});
And post the response from the server. This kind of error seems a request problem rather than server configuration issue

ajax problem with sencha touch

I am trying to submit a form using ajax in the sencha touch framework. It's a simple form that asks for a user's name, email address, and a brief message. I then want to post the data to a php script that simply emails the data to me.
The problem I have is when I try to submit the form I get the following error:
"SyntaxError: Unable to parse JSON string"
The code to send the request is as follows:
var userName = name.getValue();
var userEmail = email.getValue();
var userMessage = message.getValue();
Ext.Ajax.request({
url:'path/to/phpfile.php',
jsonData:{"name":userName, "email":userEmail, "message":userMessage},
method:"POST",
success:function(){
alert("Success!");
},
failure:function(){
alert("Error");
}
});
The error occurs in the sencha touch framework on line 14583, which is
Ext.util.JSON = {
encode: function(o){
return JSON.stringify(0);
},
decode: function(s){
return JSON.parse(s); //this is line 14583
}
};
I'm just starting to learn Ext and sencha touch so could someone please point in the right direction here? Any threads/tutorials/examples would be greatly appreciated.
Thanks in advance
Maybe your Server uses Content Negotioation. In this case it respects the Request-Header-Parameter Accept, which is Accept: */* in your case. So the Server sends your Script HTML or XML which can't be read as JSON.
Change your Code to the following:
Ext.Ajax.setDefaultHeaders({
'Accept': 'application/json'
});
Ext.Ajax.request({
url:'path/to/phpfile.php',
params:{"name":userName, "email":userEmail, "message":userMessage},
method:"POST",
success:function(){
alert("Success!");
},
failure:function(){
alert("Error");
}
});
Source: http://www.sencha.com/learn/legacy/Manual:RESTful_Web_Services
What happens if you change the Ajax Request to the following.
Ext.Ajax.request({
url: 'php/file.php',
method: 'post',
params: { id: idvar, data1: Ext.encode(schouw), data2: Ext.encode(opmerkingen) },
success: function(response) {
//Reponse
}
});
In my own application this, direct, encoding of the data to JSON works great.
Are you sure the var's you are sending are filled with data? Within my application I use the below code to substract data from the input values (slightly different);
formID.getValues().inputFieldID

Resources