I know that AngularJS prefers JSON, but I can't get my Web API to work with JSON. I've tried for 3 days and I'm not going to try anymore. I can get it to return XML. Can I retrieve the XML data with AngularJS? I have written the $http call below and it always fails with no status text. I've tried asking for XML type and I've tried the default call. You can see that all 3 of these URLs return XML data in the browser:
http://stevegaines.info/api/Exams?id=3&extra=0
http://stevegaines.info/api/Exams/4
http://stevegaines.info/api/values
$http.get(url)
.then(function (dataResponse)
{
$scope.Exams = dataResponse.data;
}, function (error)
{
alert("error.statusText = " + error.statusText);
});
I've just tried to call your api with $http service and it works ok. I think you should start investigating this problem with looking at network tab in chrome developer tools when making such a request.
Related
I have a simple angular resource that I've defined as below:
CompanyService.factory('CompanyService',
function ($resource) {
return $resource('https://baseurl.com/api/values/');
}
);
I then have a controller that calls that resource passing in a success and fail function:
.controller('companyList', function($scope, CompanyService) {
$scope.companies = CompanyService.query(
function(data) {
console.log(data);
return data;
},
function(error){
console.log("Error:");
console.log(error);
}
);
The rest API is a .NET MVC Web API that is extremely basic. I've configured it to return JSON and it simply returns an array of two objects like below. I've also enabled CORS so my angular app, which is hosted in a different domain, can call the api.
[{ID:1, Name:"TEST1"}, {ID:2, Name:"TEST2"}]
I've tested the REST call using jquery and just straight call through browser. All was functional (including the cross site scripting when calling from my angular app just using a straight JavaScript HTTP call).
When I try to call the api from my controller however, it always ends up in the error function. The error object contains a data property that is always populated with the string "resource is required|resource is required|undefined"
When I check the network I see no call to the values end point. It's as if the call is failing before ever being made.
If I change out the url to point to some sample REST api like https://jsonplaceholder.typicode.com/users/ it works fine and I'm able to see the call to "users" in the network traffic, which makes me think there is something wrong with my C# REST endpoint, however all my tests to call the REST endpoint outside of angular work successfully.
Can anyone help? I can't find anyone reporting this issues before anywhere on the net.
should the code be the one below? i didn't test it, just guess.
myModule.factory('CompanyService',
function ($resource) {
return $resource('https://baseurl.com/api/values/');
}
)
.controller('companyList', function($scope, CompanyService) {
CompanyService.query(
function(data) {
$scope.companies = data;
console.log(data);
return data;
},
function(error){
console.log("Error:");
console.log(error);
}
);
I ended up rebuilding my angular app from scratch. My first app was from the angular-seed github and had a handful of libraries already added in for testing and other things. One of those things is was was leading to this error as once I started a new project completely from scratch and added in angular and my REST call things worked perfectly. I've already spent too much time working through this so not going to spend any more time identifying exactly what it is but in case anyone else runs into the problem I did want to answer this one and close the book on it.
So, I have been working on this exercise and I'm down to one final problem.
The JSON is on a different server. If I use a plain old $http.get then it doesn't allow the cross-server request. When I switch and use $http.jsonp I get to the file but it claims an unexpected ":" right away. I've validated their JSON so I'm not sure what's going on.
This is the current implementation of the call:
app.factory('users', ['$http', function($http) {
return {
callExternalJson: function() {
return $http.jsonp('http://applicant.pointsource.us/api/testUser/577ebf34f62a2d8f3c05d9c0?callback=JSON_CALLBACK').then( function(response) {
return response;
});
}
}
}]);
How do I get that remote JSON file?
Something to note: that remote JSON changes every time you hit it.
I also tried a different way of using jsonp that I've used in the past to access other RESTful APIs and got the same result of it choking on their first colon.
The problem isn't your code, but instead the server.
Try replacing the URL with this Test URL that supports JSONP. http://ip.jsontest.com/?callback=JSON_CALLBACK
I have a form in angular where a user enters various criteria which I then want to pass to Web Api and get a result after queries are run. I originally thought of this as a "Get" but had trouble passing complex objects to the Web Api. With some advice, I then used a Post and was able to pass the criteria run the query in the Web Api but I had trouble getting the result back in Angular. The Web Api method is run and gets the results. But I don't see the results in the data service.
What is the best approach where the criteria for a query is multiple fields and some are lists? I haven't been able to find any good examples.
Here is the Web Api method:
[HttpPost]
public IEnumerable Post([FromBody] FrequentPawnerReportCriteria criteria)
{
var repo = new FrequentPawnerReport();
var result = repo.GetReport(criteria);
return result;
}`
Here is the dataservice:
function getFrequentPawner(criteria) {
return $http.post("/api/FrequentPawner/Post", criteria)
.then (getFrequentPawnerComplete)
.catch(getFrequentPawnerFailed);
function getFrequentPawnerComplete(response) {
var x = response
return response.data.results;
}
function getFrequentPawnerFailed(error) {
alert("XHR failed for frequent pawner report: " + error.responseText);
}
}
And here is the controller code:
function getTopPawnerResults(criteria) {
return DataContext.getFrequentPawner(criteria)
.then(
function (result) {
vm.frequentPawnerReport = result.data;
return vm.frequentPawnerReport;
});
}
Simply use JSON. Use JSON.stringify() to parse JSON object to string and POST it. Similarly, return JSON string from server, and assign it to variable in Angular. It will be automatically converted to JSON object.
I think when you make your post request, you need to have a callback function that would get invoked when your Web Api returns. Within that callback function you can update your $scope variables which will make your web ui show the response from the server. You can find an example of what I mean here: https://docs.angularjs.org/api/ng/service/$http
The gist of it:
$http({
method: 'POST',
url: '/path/to/your/web/api',
function(success) {
console.log('Successfully executed the api call');
$scope.response = response; // change this to match the data you are expecting from the server response
},
function(failure) {
console.error('There was an error');
$scope.failure = failure; // change this to match your failure response
}
);
Thanks for responding. The project is a mix of web forms and angularjs. I am migrating the app and didn't notice this form had a conflict which was causing a post back and making it look like the result was not being returned. I took the form into a separate project and was able to get the results I was going for.
I'm having some trouble with error handling in a little angularjs application. I'm interacting with a Flask backend and a Postgres DB.
I have a factory service
appointServices.factory('Appointments', ['$resource', function($resource){
return $resource(someUrl, {}, {
query: { ... }
,
create: {
method: 'POST'
,url: 'http://somedomain:port/new/:name/:start/:end/:treatment'
,params: { start: '#start', end: '#end', name: '#name', treatment: '#treatment' }
,isArray:false
}
});
}
]);
Inside a controller I'm making the following call
Appointments.create($scope.appointment, function(value, responseHeaders) {
// success handler
console.debug('success: ', JSON.stringify(value));
}, function(httpResponse) {
// error handler
console.debug('error: ', JSON.stringify(httpResponse));
});
Here $scope.appointment contains the relevant parameters for the create action.
Now, in the backend I'm able to catch DB errors involving constraints and I'm trying to return an error code with a 'meaningful' message. So I have a python method
def create(name, start, end, treatment):
try:
...
transaction_status = 'ok'
code = 200
except IntegrityError as e:
...
transaction_status = 'IntegrityError'
code = 500
finally:
...
return make_response(transaction_status, code)
Everything works fine, I'm able to talk to the backend, create new data and insert this in the DB. As I said, any violation of the constraints is detected and the backend responds
curl -X POST "http://somedomain:port/new/foo/bar/baz/qux" -v
...
< HTTP/1.0 500 INTERNAL SERVER ERROR
...
IntegrityError
So, the problem is, no matter whether the action create was successful or not, the intended error handler specified inside the controller is always fired. Moreover, I always end up with a status code 404 in the httpResponse. Firebug shows correctly the code 500 as above, though.
Anybody has any idea of why I'm getting this behavior?
Any suggestions on how to improve the error handling mechanism are also welcome.
Thx in advance.
P.S. Following the documentation on $resource I have also tried variations on the factory service call, e.g.
Appointments.create({}, $scope.appointment, successCallback, errorCallback);
Appointments.create($scope.appointment, {}, successCallback, errorCallback);
with the same results.
Update:
Forgot to mention the important fact that I'm interacting with the backend via CORS requests. The POST request in create above is having place with the OPTIONS method instead. As I mentioned everything is working correctly except for the error response.
Under further investigation, I tried to isolate the factory service, in case I did something wrong, and I also tried the approach shown in the credit card example ($resource docs), but with no positive result.
However, I came up with two workarounds. Firstly, I was able to create a plain JQuery POST request, as in the example shown in the docs. This time, the request is not replaced by OPTIONS and I got the error code correctly.
I also managed to connect to the backend with the low-level $http service as follows:
var urlBase = 'http://somedomain:port/new/:name/:start/:end/:treatment';
var url = urlBase.replace(/:name/g, $scope.appointment.name);
url = url.replace(/:start/g, $scope.appointment.start);
url = url.replace(/:end/g, $scope.appointment.end);
url = url.replace(/:treatment/g, $scope.appointment.treatment);
// force method to be POST
var futureResponse = $http({ method: 'POST', url: url });
futureResponse.success(function (data, status, headers, config) {
console.debug('success: ', JSON.stringify(data));
});
futureResponse.error(function (data, status, headers, config) {
console.group('Error');
console.debug(JSON.stringify(status));
console.debug(JSON.stringify(data));
console.groupEnd();
});
This time, as in the case of JQuery, the request is done effectively with POST and error codes are correctly received.
Notice also that I'm not calling $http.post but I set the method to POST as part of the object parameter to $http, otherwise the connection takes places with OPTIONS as before.
Still trying to figure out what is happening with $resource.
I'm building an AngularJS app which calls a NodeJS server that gets data from a DB.
The NodeJS returns a JSON.stringify(someArrayWithData).
Here is the AngularJS code:
$scope.getMainGroups = function(){
$http.jsonp("http://127.0.0.1:3000/get/MainGroups?callback=JSON_CALLBACK").success(function(data, status, headers, config) {
$scope.MainGroups = data;
}).error(function(data, status, headers, config) {
$scope.MainGroups = status;
});
};
$scope.MainGroups is going to the .error instead to the success even when I can see in the chrome debugger that the result came back (200 ok).
What am I missing?
You must return a valid JSON response on the server side. The 200 OK is just the GET request that is injected into the DOM. I bet you are not returning a valid JSON response from the server with right response code.
Here is an example on how to construct the response on the server side (PHP):
Simple jQuery, PHP and JSONP example?
As answered here you need to change the NodeJS response. The JSONP answer needs to start with the exact text that AngularJS added in the URL (for example 'angular.callbacks._1').
// changes in your server script used by NodeJS
// Required for JSONP calls, 'callback' matches the '?callback=JSON_CALLBACK'
app.set('jsonp callback name', 'callback');
// ... in your response change json to jsonp
res.jsonp(votes);
After doing these changes, when the server detects a 'callback' in the parameters, answers like this:
/**/ typeof angular.callbacks._1 === 'function' &&
angular.callbacks._1([{"votes":3,"title":"new topic", etc...
Now yes, AngularJS correctly calls back the 'success' function.