Reading from NegotiatedContentResult object (sent from WebAPI) in angular js promise - javascript

Displayed below is my WebAPI method which returns a list of Information about several books.
[System.Web.Http.Authorize]
public async Task<IHttpActionResult> Get(Guid id)
{
try
{
var result = await _assetAssetRepository.View(id);
if (result == null)
{
return NotFound();
}
return Content(HttpStatusCode.Found, result);
}
catch (Exception ex)
{
return Content(HttpStatusCode.InternalServerError,
"Exception Occurred" + ex.Message + " " + ex.StackTrace);
}
}
Angular js code to consume this data
var getAssetDetails = function (assetId) {
var deferred = $q.defer();
$http.get("/api/Asset/" + assetId, { headers: { 'Authorization': 'Bearer ' + $cookies.get('accessToken') } })
.then(function (response) {
deferred.resolve(response);
}).catch(function (response) {
alert("Oops something wrong: " + response.data);
deferred.reject(response);
}).finally(function () {
});
return deferred.promise;
};
The bit i am struggling is if you replace this line of code in webapi
"return Content(HttpStatusCode.OK,result)" with "return Ok(result)" i can see the data in the UI without any problem. However when i use "return Content(HttpStatusCode.OK,result)", the angular code for some cannot read this and throws out exception and shows the alert message saying "Oops something wrong [object Object]" so it seems like its getting the data but for some reason its still throwing exception. Anyone up for help?

Well, it's best to start with details given by the catch block. But one of many errors can be (which I first had):
Unexpected token R in JSON at position 0
which is be due to responseType: 'JSON' added in your http request. Angular takes the response as JSON where in this case it is not. So we need to remove this.
Here is how I do it (end-to-end). From my API:
return Content(HttpStatusCode.<statuscode>, "ResponseContent: " + "my_custom_error");
Second Case:
//If I'm getting output from another API/Layer then I pass it's output like this
var output = response.Content.ReadAsStringAsync().Result;
return Content(response.StatusCode, "ResponseContent: " + output);
And in the Angular code, I read it like this:
$http({ method: methodType, url: endpoint })
.then(function (response) {
response.status; //gets you the HttpStatusCode to play with
response.data; //gets you the ReponseContent section
}, function (response) {
response.status; //gets you the HttpStatusCode
response.data; //gets you the ReponseContent section
});
From https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the
transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to
generate the request.
statusText – {string} – HTTP status text of the response.

Related

Javascript and Django Rest Framework - cannot read property

I'm trying to retrieve data from an API endpoint that i created with Django Rest Framework. At first, my code worked but now i keep getting this error:
Uncaught TypeError: Cannot read property 'ticker' of undefined
It's weird, because the console.logstatement in the following code returns nothing, although i'm sure that there is data in the endpoint that i'm calling.
This is what the data i'm trying to retrieve looks like:
[
{
ticker: "TEST",
Price: 7876
}
]
And this is the Ajax function that i built:
function doPoll(){
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
console.log(data[0]);
$('#data').text(data[0].ticker + ' ' + data[0].Price);
setTimeout(doPoll, 100);
});
}
doPoll();
And this is where the data should appear:
<h3 id="data"></h3>
The function should be supposed to place my data on my html page and refresh that data every second.
http://127.0.0.1:8000/tst/ is the DRF API endpoint that i'm trying to call, from where i'm retrieving the JSON data.
you need to access data.results... this is standard DRF response format
function doPoll(){
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
var results = data.results;
console.log(results[0]);
$('#data').text(results[0].ticker + ' ' + results[0].price);
setTimeout(doPoll, 100);
});
}
doPoll();
You have a typo here data[0].Price should be data[0].price
$.getJSON('http://127.0.0.1:8000/tst/', function(data) {
if(data && data.length > 0){
console.log(data[0]);
$('#data').text(data[0].ticker + ' ' + data[0].Price);
setTimeout(doPoll, 100);
}else{
//console.log('No Data')
console.log("DATA is: ", data)
}
});
Validate that data[0] exists before accessing properties of it
The best way to debug this is to check the response in your browser dev tools
Network tab

Call Wordnik API from NodeJS using Swagger

I am having problems trying to use the Wordnik API via Swagger (NodeJS).
I am trying to follow this documentation: swagger-api
The Wordnik API can be founded here: hhttp://developer.wordnik.com/docs.html#!/word/getRelatedWords_get_4
The JSON description of the Wordnik API: hhttp://developer.wordnik.com/v4/word.json
I am trying to call the GET /word.json/{word}/relatedWords method with the following parameters:
{word:"cars", useCanonical:true, relationshipTypes:"synonim", limitPerRelationshipType:10}
The Wordnik API requires authentification, according to the swagger-api documentation I have written the following code:
var Swagger = require('swagger-client');
var client = new Swagger({
url: 'http://developer.wordnik.com/v4/word.json',
success: function() {
client.word.getRelatedWords({word:"cars",useCanonical:true,relationshipTypes:"synonim",limitPerRelationshipType:10}, function(success){
console.log('succeeded and returned this object: ' + success.obj);
},
function(error) {
console.log('failed with the following: ' + error.statusText);
});
},
authorizations: {
api_key: new Swagger.ApiKeyAuthorization('api_key', 'MY_WORDNIK_API_KEY', 'query'),
}
});
My main problem is that I do not know how to write properly the code to call that method with that parameters. The code written above returns this error:
failed with the following: {"message": "unauthorized", "type":
"error"}
Any idea about how to write the code to make that call?
Two things: one, the Swagger url for Wordnik should be
http://api.wordnik.com/v4/word.json
Two, you need to use 'synonym', not 'synonim'.
I tried your code with both these changes and it works fine for me.
Also, I'm not sure why you're using Swagger.js here? It's definitely cooler, but you can call the API with request, e.g.:
request("http://api.wordnik.com:80/v4/word.json/"+'car'+"/relatedWords?useCanonical=false&relationshipTypes=synonym&limitPerRelationshipType=10&api_key=YOURKEYHERE", function (error, response, body) {
if (error || response.statusCode !== 200 || (body == "")) {
console.log(word + " had error: " + error)
return callback(error || {statusCode: response.statusCode});
}
else {
// console.log(word);
callback(null, JSON.parse(body));
}
});

Passing JSON data with request using $http.get() or $http.post()

I'm trying to call a webservice that requires me to pass a JSON object to it. Though I'm not sure whether I'm doing it right. My service does the following:
this.updateAddressDetails = function (address, personId) {
var url = 'http://213.456.123.456:8080/Address?' +
'action=updateAddress' +
'&personId=' + personId +
'&address=' + JSON.stringify(address);
return $http.get(url);
}
But I get the following error server side (I'm using Java Servlets):
Error parsing HTTP request header
Which leads me to assume that I'm not passing the JSON to the server the correct way. Any tips?
Try something like this if your are working with angular JS:
$scope.myFunc = function() {
// Simple POST request example (passing data) :
$http.post("/createProject/"+ id +"", {
projectTitle: pTitle,
userID : id
}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
console.log("project created");
console.log("this is the response data " + data);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};

Access header's properties within a $http call in AngularJS

Following github API's documentation for pagination, I'm trying to request event items and retrieve the Link header (just like they suggest) to build the pagination. The problem is that I don't know how to handle the headers('Link') object.
Function:
getEvents: function(page) {
if(cacheService.get('eventos_'+page)) {
return cacheService.get('eventos_'+page);
} else {
var deferred = $q.defer();
$http.get('https://api.github.com/repos/'+owner+'/'+repo+'/events', {params: {per_page: 15, page: page}})
.success(function(events, status, headers) {
console.log(events, status, headers('Link'));
cacheService.put('eventos_'+page, events);
deferred.resolve(events);
}).error(function(err) {
deferred.reject('Error', err);
});
return deferred.promise;
}
}
The resulting "object" (if it can be called like that) is:
"
<https://api.github.com/repositories/XXXXXX/events?page=2&per_page=15>; rel="next",
<https://api.github.com/repositories/XXXXXX/events?page=4&per_page=15>; rel="last"
"
¿How can save page (next and last) numbers in $scope variables? or at least how can I traverse that object?
Don't laugh, but I tried headers('Link').rel['last'] without success, of course.
From the angular $http document https://docs.angularjs.org/api/ng/service/$http
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
And to get data from headers its headers['Link'] if you can see 'Link' in your response header
Below is the code to get pagination links from header if you are sending pagination parameters in response header
function parseHeader(header){
// Split parts by comma
var parts = header.split(',');
var links = {};
// Parse each part into a named link
angular.forEach(parts, function (p) {
var section = p.split(';');
if (section.length != 2) {
throw new Error("section could not be split on ';'");
}
var url = section[0].replace(/<(.*)>/, '$1').trim();
var queryString = {};
url.replace(
new RegExp("([^?=&]+)(=([^&]*))?", "g"),
function($0, $1, $2, $3) { queryString[$1] = $3; }
);
var page = queryString['page'];
if( angular.isString(page) ) {
page = parseInt(page);
}
var name = section[1].replace(/rel="(.*)"/, '$1').trim();
links[name] = page;
});
return links;
}

order of operations parse cloud

I was wondering what the order of operations are in the parse cloud. I currently am running into trouble trying to do multiple things at once inside my job on the cloud. I am currently trying to make an HTTP request for each user in my user table (there are 2) and then get the webpage or httprequest.text from the webpage. My code is as followed
Parse.Cloud.job("WeatherUpdates2", function(request, status) {
var query = new Parse.Query(Parse.User);
query.exists("City");
query.each(
function(result){
var object = result;
console.log(object.id);
var city = object.get("City");
city = city.replace(" ", "");
city = city.replace(" ", "");
// get the country code.
var countryCode = object.get("CountryCode");
var woeidUrl = "http://where.yahooapis.com/v1/places.q(" + city + "," + countryCode + ")?appid=(appid)";
console.log(woeidUrl);
var woeID = "An error occured retrieving your WOEID.";
Parse.Cloud.run('httpRequest', { url: woeidUrl }, {
success: function(WOEID) {
console.log("returned from http request.");
},
error: function(error) {
console.log("Error occurred while making request for WOEID " + error.message);
status.error(error.message);
}
});
},
{
success: function() {
// results is an array of Parse.Object.
console.log('#Query');
status.success("Updated Records!!");
},
error: function(error) {
// error is an instance of Parse.Error.
console.log('#error');
response.error("Failed to save vote. Error=" + error.message);
}
});
});
Where the job httpRequest is:
Parse.Cloud.define("httpRequest", function(request, response) {
var webpage = "Something went wrong.";
Parse.Cloud.httpRequest({
url: request.params.url,
success: function (httpResponse) {
webpage = httpResponse.text;
webpage = webpage.toString();
response.success(webpage);
},
error: function (error)
{
console.log("Error in http request " + error.message);
response.error(error.message);
}
});
});
now I would expect to be printed would be the, object id of first user, their url, the job running, the message"returned from http request." then repeated another time for the second user and finally the job finishing with the message "Updated Records". but instead I get:
I2014-07-22T15:15:16.013Z] A5hod7qKE3
I2014-07-22T15:15:16.045Z] http:/where.yahooapis.com/v1/places.q(Draper,US)?appid=(appid)
I2014-07-22T15:15:16.053Z] GmuqxpTUpM
I2014-07-22T15:15:16.066Z] http:/where.yahooapis.com/v1/places.q(SaltLakeCity,US)?appid=(appid)
I2014-07-22T15:15:16.082Z] #Query
I2014-07-22T15:15:16.131Z] v385: Ran cloud function httpRequest with:
Input: {"url":"http://where.yahooapis.com/v1/places.q(SaltLakeCity,US)?appid=(appid)"}
Result:
2487610TownSalt Lake CityUnited StatesUtahSalt LakeSalt Lake City40.777561-111.93071740.699890-112.10125740.852951-111.739479511America/Denver
I2014-07-22T15:15:16.141Z] v385: Ran cloud function httpRequest with:
Input: {"url":"'http://where.yahooapis.com/v1/places.q(Draper,US)?appid=(appid)'"}
Result:
http://where.yahooapis.com/v1/schema.rng'" xmlns:yahoo="http://www.yahooapis.com/v1/base.rng" yahoo:start="0" yahoo:count="1" yahoo:total="11">2393601TownDraperUnited StatesUtahDraper8402040.524139-111.86627240.442921-111.92212740.544361-111.78304349America/Denver
I removed 1 / from both the printing urls so I could posts this because I don't have high enough rep to post more than 2 links. I also have put in my appid into the (appid) so the url does return to me the according woeid from yahoo.com. The problem here being I can't actually get into the success function of the http request job. Any help is greatly appreciated!
EDIT:
I was trying to figure out how to run a job in a for loop but couldn't get it to work. I tried to make a promise and do what Fosco said below, but have had no luck. Here is my code.
for(var i = 0; i < woeIDs.length; i++)
{
console.log("hello");
var weatherURL = "http://weather.yahooapis.com/forecastrss?w=" + woeIDs[i] + "&u=f";
var promise = Parse.Cloud.run('httpRequest', { url: weatherURL }, {
success: function(WOEID) {
console.log("got here");
},
error: function(error) {
console.log("Error occurred while making request for WOEID " + error.message);
status.error(error.message);
}
});
Parse.Promise.when([promise]).then(function() { status.success(); });
}
if I run this code I get a hello twice then the two job calls then the "got here" message once. I have tried adding a return statement to it and with no luck also. Thanks again for all the help!!!
The issue here is that inside the each callback, you need to return the promise from your cloud function call if you want to ensure the tasks complete, and have it wait before going to the next object.
Simplified and using promises:
query.each(function(object) {
...
return Parse.Cloud.run(...);
}).then(function() {
// success
}, function(err) {
// error
});
For looping over a promise-returning function like Parse.Cloud.run:
var promises = [];
for (i = 0; i < 5; i++) {
promises.push(Parse.Cloud.run('...', {}));
}
Parse.Promise.when(promises).then(function() {
// all done
}, function(err) {
// error
});

Categories

Resources