Retrieve a Sharepoint List with Angular JS - angularjs

I have created an Angular JS application which would output a list of data in a Share Point list. I am trying to make a rest API call to my Share Point List to get the data, however I am unable to do it as I get an error 403 Forbidden.
Below is my controller which tries to fetch the data.
app.controller('RetrieveRecords', function ($q, $http, $scope) {
var url = "https://testapp.sharepoint.com/sites/testmyapplication/_api/web/lists/getByTitl
e('TestAppList')/items?$select=Status,Time";
$http(
{
method: "GET",
url: url,
headers: { "accept": "application/json;odata=verbose" }
}
).success(function (data, status, headers, config) {
$scope.details = data.d.results;
}).error(function (data, status, headers, config) {
});
});
My Angular JS application is not a Share Point page, my application is basically hosted as a Azure Static Website. I checked some online tutorials, however I couldn't find a solution to the problem I am facing.
Thank you.

#John,
You have to supply digest within the header.
You will find the necessary value in the element called '__REQUESTDIGEST'. So with jQuery you can get the value like this: $('#__REQUESTDIGEST').val().
This value needs to be added to the header:
headers: { "Accept": "application/json;odata=verbose", "X-RequestDigest": $('#__REQUESTDIGEST').val() }
can you try adding this tag and see if it works.
Hope it helps.
MV

Related

Pass Data List from angularjs to webservice?

I'm working on app in ionic 1 platform using angularjs, in which I want to Pass List of object to Web-service, How can I do it?
I have tried doing this but was not able to send any Data..
Here is my code and how to pass list of object in data: $scope.AddNew
$http({ url: $rootScope.HostName + '/bulk', dataType: 'json', method: 'POST', contentType: "application/json; charset=utf-8", data: $scope.AddNew, headers: { 'content-type': 'application/json' } }).success(function (response) { alert("Success"); }).error(function (error) { });
If there is another approach or way to do it then please do help
Thanks in advance.
Assuming your $http call is in the controller where you can access $scope.
The way you had passed is correct, but at the server side you should accept your request body as an Array of objects.
If your server side is java spring app,
You would design your method with #RequestBody YourClass[] objs
I think your code is correct, just so it is simple and readable I would suggest this format:
$http.post($rootScope + '/bulk', $scope.AddNew).then(function(response) {
alert("Success");
}, function(error) {
})
The promise structure in AngularJS has since been updated. In regard to your question, the code should work fine if you can access AddNew through your $scope. Make sure you are handling your requests properly in the backend. Try logging for checking if data is sent and received.

Angularjs - 500 (Internal Server Error) on $http Post

I am new to Ionic and angular. I am building a sample with ionic framework using angular.js. I want to call WebApi through $http post method. I checked this(ionic-proxy-example) solution and I am trying to implement the same using my api. When I call the api provided in above example in my sample project, I get the records but its not working with my api. It throws 500 internal error.
Here is my app.js
angular.module('myApp', ['myApp.controllers', 'myApp.services'])
.constant('ApiEndpoint', {url: 'http://localhost:8100/api'})
Services.js
angular.module('myApp.services', [])
.factory('Api', function($http, $q, ApiEndpoint) {
console.log('ApiEndpoint', ApiEndpoint)
var getApiData = function() {
var q = $q.defer();
var data = {
Gameweek_ID: '179',
Vender_ID: '1',
Language:'en'
};
var config = {
headers : {
"Content-Type": "application/json; charset = utf-8;"
}
};
$http.post(ApiEndpoint.url, data, config)
.success(function (data, status, headers, config) {
// $scope.PostDataResponse = data;
alert('success');
console.debug("response :" + data);
q.resolve(data);
})
.error(function (data, status, header, config) {
// $scope.ResponseDetails = "Data: " + data +
alert('error');
console.debug("error :" + data);
q.reject(data);
});
return q.promise;
}
return {getApiData: getApiData};
})
controllers.js
angular.module('myApp.controllers', [])
.controller('Hello', function($scope, Api) {
$scope.employees = null;
Api.getApiData()
.then(function(result)
{console.log("result is here");
jsonresponse = result.data;
$scope.employees = jsonresponse;}
)
});
And Ionic.Project File
{
"name": "Multilingual",
"app_id": "4b076e44",
"proxies": [
{
"path": "/api",
"proxyUrl": ""
}
]}
I am trying to understand the problem and checked multiple methods to call the api. Surprisingly, it works with ajax post call without any CORS errors. As I am using Angular, I am trying to get this done through $http post. I feel it is some minor issue but I am not able to figure out. Will be grateful for solutions. Thank you.
You've set the content type to json so the sever is expecting a json string but isn't receiving a properly formatted json string as you're sending through an object and hence the error.
Where you have $http.post(ApiEndpoint.url, data, config) change it to $http.post(ApiEndpoint.url, JSON.stringify(data), config).
If that doesn't work, change your content type to application/x-www-form-urlencoded and update this line $http.post(ApiEndpoint.url, data, config) to $http.post(ApiEndpoint.url, $httpParamSerializer(data), config) , don't forget to inject the $httpParamSerializer function.
The problem is that you are sending a POST with $http.post request instead of a GET request with $http.get
Try as below-
$http({
url: ApiEndpoint.url,
method: "POST",
data: data,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).Success(..rest code goes here..)
In WebAPI, when we pass more than one object in POST method, we get 500 internal error and hence we use ViewModel in such scenarios(talking about asp.net MVC).

Angular REST cannot return simple data

I am trying to get a $http REST GET call working in my Appgyver project working but nothing I do seems to come right, always returns an error.
Please note the angular app will be running on mobile devices eventually and then connect to my remote web service.
I've double checked that my custom API is working and returning data correctly in a number of ways, namely:
hard coded cUrl request running from sh files in terminal - Returns data and correct 200 code
Tested the API end points in both POSTMAN and Firefox's SOA client.
Putting in my test end point of http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term returns data as below:
[{"tid":"1","vid":"2","name":"ACME Ltd.","description":"","format":"filtered_html","weight":"0","parent":"0","uri":"http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term/1"},{"tid":"2","vid":"2","name":"ABC Films LTD","description":"","format":"filtered_html","weight":"0","parent":"0","uri":"http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term/2"}]
Even a simple CSRF Token request gives me errors.
Could someone possibly point out where I am going wrong here, the Appgyver site is badly documented and I have tried the Angular RESTful sample which my code below is based upon from https://docs.angularjs.org/api/ng/service/$http and https://docs.angularjs.org/api/ng/service/$http#setting-http-headers
Please note the code below is basically Angular.js using Javascript syntax (as opposed to Coffeescript), logging output follows the code
angular
.module('main')
.controller('LoginController', function($scope, supersonic, $http) {
$scope.navbarTitle = "Settings";
$scope.stoken = "Response goes here";
$scope.processLogin = function(){
var csrfToken;
steroids.logger.log("START CALL: processLogin");
// $form_login_email_address = $scope.login_email;
// $form_login_password = $scope.login_password;
$local_get = "http://somesite.com/quote-and-buy-performance/services/session/token";
$hal_get_taxterm_index = "http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term";
// $http.defaults.headers.common.contentType('application/json');
var req = {
method: 'GET',
url: $hal_get_taxterm_index,
headers: {
'Content-Type': 'application/json'
}
}
$http(req)
.success(function(data, status, headers) {
steroids.logger.log("Inside http.get() success");
}).error(function(data, status, headers){
steroids.logger.log("Inside http.get() WITH ERROR");
steroids.logger.log('data: ' + data);
steroids.logger.log('status: ' + status);
}).then(function(data, status, headers){
steroids.logger.log("Inside http.get() then");
});
steroids.logger.log("END CALL: processLogin");
}
});
Logging output from calls to steroids.logger.log
View Time Level Message
main#login 16:01:55.219 info "Inside http.get() WITH ERROR"
main#login 16:01:55.219 info "data: null"
main#login 16:01:55.219 info "status: 0"
main#login 16:01:55.64 info "END CALL: processLogin"
main#login 16:01:55.64 info "START CALL: processLogin"
Here's what I would do:
Separate out your http call into a service. This is a pretty standard way to modularize your code in angular:
angular.module('main').factory("SomeService", function($http) {
return {
get: function() {
$http({
url: "http://somesite.com/quote-and-buy-performance/druidapi/taxonomy_term",
method: "GET",
headers: {
"Content-Type": "application/json"
}
}).success(function(data, status, headers, config) {
console.log("Success!");
console.log(data);
}).error(function(data, status, headers, config) {
console.log("Error!");
console.log(status);
console.log(data);
});
}
}
})
Then to use this in your controller, just include it in your controller declaration and call get like you would a normal method:
angular.module('main').controller('LoginController', function($scope, supersonic, SomeService) {
$scope.navbarTitle = "Settings";
$scope.stoken = "Response goes here";
$scope.processLogin = function(){
var csrfToken;
steroids.logger.log("START CALL: processLogin");
SomeService.get();
steroids.logger.log("END CALL: processLogin");
}
})
Do this and then comment back with your results and we can work from there.
If your angular's app is within a certain domain, then HTTP request must be made within the same domain.
In your case, you are trying a cross domain request (a request on another domain). You must then make a cross domain request.
You can see this question.
The author uses $http.jsonp() to send cross domain requests. There migth be another way to do it.

What is the correct architectural pattern for cross domain REST call in AngularJS?

I've created an AngularJS service that is hitting the Salesforce REST API directly from the client. However, I haven't been able to get it working due to same origin restrictions. Even when accessing non authenticated REST services and trying both $http, $http.json and Ajax. I've also tried lots of combinations of Json, Jsonp etc.
Given that I've had so many issues I'm thinking that my general approach is incorrect. Perhaps I need to setup a proxy server for this? My backend is Firebase so I don't currently have my own server.
I don't believe that the Salesforce API supports CORs and I cannot change that.
Here is an example of what I tried using $http and Ajax.
return $http.jsonp('https://na1.salesforce.com/services/data/',{
headers: {
'Content-type': 'application/json', 'Accept': 'application/json'
}}).
success(function (data, status, headers, config) {
callback(data);
console.debug(data.json);
}).
error(function (data, status, headers, config) {
console.debug("getVersions: failed to retrieve data: "+eval(data));
});
$.ajax({
url: 'https://na15.salesforce.com/services/data',
type: "GET",
dataType: "jsonp",
beforeSend: function(xhrObj){
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Accept","application/json");
xhrObj.setRequestHeader("X-Requested-With", "XMLHttpRequest");
},
success: function (data) {
console.debug(data);
callback(data);
},
error: function(data) {
}
});
You need to go into Remote Settings within SalesForce then CORS and whitelist the domain name...
I had the same issue and it seemed to have resolved the issue.
See if this helps here

Angular JS Custom Headers on GET Turns to Options

So, this has been a huge struggle for us.
We have a web API .net MVC4 back-end. We are using angular for client-side. We have a page that has some JSON that we receive data from. When we make a GET to this page we receive data. As soon as we add custom headers to the call the GET turns into OPTIONS and we get a 200, with no response. We are doing a couple things like creating a BASE64 code on "login" storing it as a cookie and trying to add that to the GET headers. the thing is we have stripped out all of the unnecessary code and we are still at the same problem. Even with authorization turned off for the data. Here is the GET code:
myApp.factory("projectDataService", function ($http, $location, $cookieStore) {
var token = "";
token = $cookieStore.get('token');
return {
getProject: function (successcb) {
$http({ method: "GET", url: "http://dev.projnik.com/api/project", headers: { 'Authorization': 'Basic ' + token } }).
success(function (data, status, headers, config) {
successcb(data);
}).
error(function (data, status, headers, config) {
console.log(data, status, headers, config);
});
},
save: function (project) {
$http({ method: "POST", url: "http://dev.projnik.com/api/project", data: $.param(project) }).
success(function (data, status) {
if (status == '201') {
$location.path('/all');
}
})
}
};
});
And the app.js:
var myApp = angular.module('Project', ['ngResource', 'ngCookies']);
myApp.config(function($routeProvider){
$routeProvider.
when('/new', {templateUrl:'templates/new.html', controller:'EditProjectController'}).
when('/mobile', {templateUrl:'templates/mobile.html', controller:'ProjectController'}).
when('/it', {templateUrl:'templates/it.html', controller:'ProjectController'}).
when('/writing', {templateUrl:'templates/writing.html', controller:'ProjectController'}).
when('/all', { templateUrl: 'templates/all.html' }).
when('/cookie', { templateUrl: 'partials/cookiecontrollerhtml.html' }).
when('/login', { templateUrl: 'partials/_login.html' }).
otherwise({ redirectTo: '/all' });
});
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);
Again, without adding headers attribute to the call, everything works (obviously we get a 401 with Authorization turned on in the API). We are willing to pay for an answer at this point.
We are exposing our actual domains here, and that is fine. If someone goes to www.projnik.com and clicks the login link on the top and enter shane, password for username,password they would receive the cookie and it routes the user back to the #/all page where they would GET the data, though it doesn't work.
PS: I have tried to ad withCredentials = true; to the call and I get the same result.
If you are accessing API in dev.projnik.com from a web page in www.projnik.com, in a browser like Chrome, CORS comes into play. If you make a GET without any custom headers, it is a simple CORS request and I assume you have settings in web.config that sends Access-Control-Allow-Origin header and that makes it work. Once you add a custom header, it is no longer a simple CORS and it becomes pre-flighted CORS with browser making an OPTIONS request. The response to this OPTIONS request must send the correct CORS headers for the browser to make the subsequent GET. To enable CORS, check this out. BTW, in IIS there is a default handler that answers OPTIONS call that you might need to remove for the message handler in Web API to respond to OPTIONS.
I am working with Shane on this - the block of code on the server is:
public void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
//These headers are handling the "pre-flight" OPTIONS call sent by the browser
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
I believe this takes care of the situation. But the problem is still there.

Resources