cross domain issue when accessing sharepoint list from sharepoint app - sharepoint

This is my code
function getListItem(url, listname, id, complete, failure) {
// Getting our list items
$.ajax({
url: url + "/_api/lists/getbytitle('"+ listname +"')/items",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
// Returning the results
complete(data);
},
error: function (data) {
failure(data);
}
});
};
The url is coming correctly, also on checkng the full url parameter in ajax call, it is returning data when i open that in new tab
But since this ajax call is made inside a sharepoint app that is in a different domain, its throwing an error - No 'Access-Control-Allow-Origin' header is present on the requested resource
What change should i make in my site to make that list available for cross domain call.
Info:
the site url is http://www.vignesh.cloudappsportal.com/
The app url is xxxx.apps.cloudappsportal.net/CloudAppsTrial/Pages/Default.aspx

Cross domain calls are blocked by modern web browsers due to security concerns. This is a common issue in web based development and is particularly relevant due to the nature of SharePoint hosted Apps. For example, when accessing data in the parent web (http://consoto.sharepoint.com) from an App (hosted at http://apps.sharePoint.com/SPApp) the calls will be blocked. To get round this you can use the SP.RequestExecutor.js script to relay messages to SharePoint from within the same domain.
Example
function getListItems(hostUrl,appWebUrl, listTitle,success,error)
{
var url = appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getbytitle('" + listTitle + "')/items?#target='" + hostUrl + "'";
var executor = new SP.RequestExecutor(appWebUrl);
executor.executeAsync(
{
url: url,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var data = JSON.parse(data.body);
success(data.d.results);
},
error: error
});
}
Usage
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var appWebUrl = getParameterByName('SPAppWebUrl');
var hostUrl = getParameterByName('SPHostUrl');
var scriptbase = hostUrl + '/_layouts/15/';
$.getScript(scriptbase + "SP.RequestExecutor.js", function (data) {
getListItems(hostUrl,appWebUrl, 'Tasks',function(data){
//print list items properties
data.forEach(function(item){
console.log(item.Title);
});
},
function(error){
//error handling goes here...
});
});
About App permissions
An app for SharePoint uses permission requests to specify the permissions that it needs to function correctly. The permission requests specify both the rights that an app needs and the scope at which it needs the rights. These permissions are requested as part of the app manifest. The following picture demonstrates how to grant read access for an App
Follow App permissions in SharePoint 2013 for a more details.

Related

Trying to send a POST request using the body of a GET request

I am currently working on a project to create API routes for two third party applications to communicate with one another using NodeJS/express. The issue I am having is that I am trying to have third party application A (3PA) get a list of timeslots from a calendar in third party application B (3PB) and then send a message to a user in 3PB containing those timeslots.
The route looks like this:
router.post('/request_appointment_times', function(req, res){
**google sheets api logic**
async function gsrun(client){
**getting data from google sheet**
var request = require('request');
require('request-debug')(request);
var options = {
'method': 'GET',
'url': '3PB API URL',
'headers': {
'accept' : '*/*',
'Authorization': 'Bearer ' + apiKey,
'content-type' : 'application/json'
},
};
request(options, function (error, response) {
if (error) throw new Error(error);
//console.log(response.body);
else
res.json({"message": "It Works!",});
slotsList = new String(response.body.slots);
slotsListArr = slotsList.split(',');
var rnd = Math.random(0, slotsListArr.length);
ssn.providedSlots = slotsListArr[rnd];
ssn.providedSlots2 = slotsListArr[rnd];
if (ssn.providedSlots == ssn.providedSlots2) {
ssn.providedSlots2 = ssn.slotsListArr[rnd]
}
if (ssn.providedSlots == ssn.providedSlots2) {
ssn.providedSlots2 = ssn.slotsListArr[rnd]
}
console.log(providedSlots);
console.log(providedSlots2);
});
}
});
Currently, I can't even get the providedSlots to print as the request function won't communicate with the console. My question is, is it possible/how can I do a POST to 3PB using the response body from my GET request within this same route. I apologize if I worded this poorly or didn't provide enough information. Any help is much appreciated and if I need to provide additional information let me know!
By the looks of this you are defining gsrun in your route handler but aren't actually invoking it. Should be more like this:
function gsrun() { /* logic */ }
router.post('/request_appointment_times', function(req, res){
gsrun();
});

Issue in making cross-domain call to Project server oData feed from SharePoint Add-In (app)

I am developing a SharePoint Hosted Add-In which will display project server projects. I am using SP.RequestExecutor to make cross domain calls. It gives me the following error “Cannot find resource for the request ProjectData.”
I have given the Reporting (Project Server) Read permission in AppManifest file. Following is my code.
$(document).ready(function () {
SP.SOD.executeFunc('SP.js', 'SP.ClientContext', initializePage);
});
function initializePage() {
hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
appweburl = decodeURIComponent(getQueryStringParameter("SPAppWebUrl"));
var scriptbase = hostweburl + "/_layouts/15/";
$.getScript(scriptbase + "SP.RequestExecutor.js", getProjectList);
}
function getProjectList() {
var executor;
executor = new SP.RequestExecutor(appweburl);
executor.executeAsync({
url: appweburl + "/_api/SP.AppContextSite(#target)/ProjectData/Projects?$filter=ProjectState eq 'In Progress'&$select=ProjectId,ProjectName&#target='" +
hostweburl + "'",
method: "GET",
crossDomain: true,
headers: { "Accept": "application/json; odata=verbose" },
success: function (data) {
var jsonObject = JSON.parse(data.body);
alert(jsonObject.d.results);
},
error: function (error) {
alert(error.body);
}
}
);
}
There is no need to use SP.AppContextSite(#target).
Try below URL -
url: appweburl + "/_api/ProjectData/Projects?$filter=ProjectState eq
'In Progress'&$select=ProjectId,ProjectName"
The permissions for your app should include Read permissions for Reporting.

Mailchimp Restful API 3.0 in Node.js always Resource not Found

I'm trying to hit one of the mailchimp's api, but for somehow I always get
{
"type": "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/",
"title": "Resource Not Found",
"status": 404,
"detail": "The requested resource could not be found.",
"instance": ""
}
I'm using request library to make the request and see the code below
var uniqueListId = "XXXX";
var apiKey = "XXX";
.post(function(req, res) {
var email = req.body.email;
var status = "subscribed";
request({
url: 'https://usX.api.mailchimp.com/3.0/lists/' + uniqueListId + '/members',
headers: {
'Authorization': 'randomUser ' + apiKey,
'Content-Type': 'application/json',
},
method: 'POST',
json: {
email_address: email,
status: status
}
}, function(err, response, body) {
if (err) {
res.json(err);
} else {
res.json(response.statusCode, body);
}
});
});
For the sake of clarity, this is the documentation that I'm referring to http://developer.mailchimp.com/documentation/mailchimp/reference/lists/members/
Is it because of my req.body data?
I agree with #TooMuchPete, The same issue happened with me and scratched my head for a whole day to solve that issue, and finally, I've found that Audience Idlist_id is wrong.
we need to pick the one which is located under the AudienceTab > ViewContacts > Settings > Audience and Defaults > Audience ID, but unfortunately, I have picked the one which is showing in the URL.
If you're getting a 404 it's because the URL you're hitting doesn't refer to an actual resource. Probably uniqueListId is either empty or not the right ID.
I would suggest using the Postman chrome add-on app to play with the requests and posts - you could also use it to generate sample code, in most languages. It is great for debugging.
After using it, I found that your request options should look something like:
let requestOptions = {
hostname: 'us14.api.mailchimp.com',
method: 'GET',
path: '/3.0/lists' + listId,
headers: {
'Authorization': 'User ' + config.mailChimp.apiKey,
'Content-Type': 'application/json',
},
}
You're almost certainly confusing mailchimp's web_id with list_id. The list_id is the one you need for the API, the web_id is the one you see in the url when you open your list.
I have absolutely no idea why mailchimp uses 2 different ids, nor why they don't seem to put it forward in any of their developer documentation.
Below is an article which explains how to find it - basically you go to your list -> settings tab -> list name and defaults.
https://3by400.com/get-support/3by400-knowledgebase?view=kb&kbartid=6

Access denied, SharePoint app. Copy file to another site collection

UPDATE: I understand now that by installing an app in web scope, it only gets access to the hostweb and appweb. So I tried to batchinstall the app - and now the APP works.
However, the App Part isnt available other than in the App Catalog.
Does Anyone know a way to give the App Part permissions to other site collections, or batch install the App Part so its available in other places than app catalog?
have this code that I'm using for downloading a file from one sitecollection, and trying to upload it to another, in sharepoint online.
I'm getting a 403 that im not allowed to upload the file. The DOWNLOAD is fine.
Does anyone have any clues?
var web;
var hostweburl;
var appweburl;
$(document).ready(function () {
sharePointReady();
});
function sharePointReady() {
hostweburl =
decodeURIComponent(
getQueryStringParameter('SPHostUrl')
);
appweburl =
decodeURIComponent(
getQueryStringParameter('SPAppWebUrl')
);
var scriptbase = hostweburl + '/_layouts/15/';
$.getScript(scriptbase + 'SP.Runtime.js',
function () {
$.getScript(scriptbase + 'SP.js',
function () { $.getScript(scriptbase + 'SP.RequestExecutor.js', copyAndUploadFile); }
);
}
);
}
function getQueryStringParameter(param) {
var params = document.URL.split("?")[1].split("&");
var strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == param) {
return singleParam[1];
}
}
}
function copyAndUploadFile() {
var targetUrl = "https://sogetiumea-my.sharepoint.com/personal/simonagren_sogetiumea_onmicrosoft_com";
var executor = new SP.RequestExecutor(appweburl);
var fileContentUrl = "_api/SP.AppContextSite(#target)/web/GetFileByServerRelativeUrl('/_catalogs/theme/15/fontscheme003.spfont')/$value?#target='" + hostweburl + "'";
var fileTargetUrl = "_api/SP.AppContextSite(#target)/web/GetFolderByServerRelativeUrl('_catalogs/theme/15')/Files/Add(url='fontscheme003.spfont', overwrite=true)?#target='" + targetUrl + "'";
$.ajax({
url: "_api/contextinfo",
type: "POST",
contentType: "application/x-www-url-encoded",
dataType: "json",
headers: {
"Accept": "application/json; odata=verbose",
},
success: function (data) {
var digest = data.d.GetContextWebInformation.FormDigestValue;
var getFileAction = {
url: fileContentUrl,
method: "GET",
binaryStringResponseBody: true,
success: function (getFileData) {
var results = data.body;
var copyFileAction = {
url: fileTargetUrl,
method: "POST",
headers: {
"Accept": "application/json;odata=verbose",
"X-RequestDigest": digest
},
contentType: "application/json;odata=vebose",
binaryStrinRequestBody: true,
body: getFileData.body,
success: function (copyFileData) {
alert("kopiering gick bra");
},
error: function (ex) {
alert(JSON.stringify(ex));
}
};
executor.executeAsync(copyFileAction);
},
error: function (ex) {
alert(JSON.stringify(ex));
}
};
executor.executeAsync(getFileAction);
},
error: function (ex) {
alert(JSON.stringify(ex));
}
});
}
I used a workaround of sort.
I added the app part to the app catalog, and used a hardcoded value to the mysite site collection (used as source for downloading/copying the file).
Using developer tools I copied the html for the iframe used to show the app part i n the app catalog.
I activated publishing on mysites root site collection.
I added a scripteditor webpart. Then I added the copied iframe code. Voila, now the "app part" works.
At first the app listens to the current user, checks if a personal site exists, else it creates it.
Copies as cusom spcolor file from the mysite "_catalogs/theme/15" to same folder on the current users personal site.
Applies the spcolor file in "Applytheme".
This is based on the idea that Vesa has done with a provider hosted app!

Issuing caching results of REST service created using ServiceStack and accessed through jQuery

I have a REST service created using ServiceStack that I'm consuming from jQuery running in a mobile browser. Everything works fine until I attempt to implement caching within the service using the MemoryCacheClient. As soon as I insert the code to cache the results I don't get any response returned to the browser. When I look at the request\response in Fiddler I get the following error:
Response is encoded and may need to be decoded before inspection. Click here to transform.
If I just access the service directly from the browser it works fine, it only seems to be an issue when accessed through .ajax method in jQuery.
Here's the service code
public override object OnGet(Products request)
{
string cacheKey =
UrnId.Create<ProductsService>("productCategoryType", request.ProductCategoryType.ToString());
return base.RequestContext.ToOptimizedResultUsingCache(this.CacheClient, cacheKey, () =>
{
//var service = this.ResolveService<ProductsService>();
ProductsResponse response = new ProductsResponse();
response.Products = GetLoanTypes(request.ProductCategoryType);
return response;
});
}
And then the Ajax
var serviceUrl = "http://local.standard.id.com/MobileServices/Products/";
var products = new Object();
products.ProductCategoryType = id;
$.ajax({
type: "GET",
contentType: "application/json",
url: serviceUrl,
data: products,
dataType: "jsonp",
success: function (data, textStatus) {
if (textStatus == "success") {
productData[id] = data;
displayProducts(data, id);
}
},
error: function (xhr, err) {
alert(err);
}
});
As soon as I comment out the caching in the service and just always return the raw results everything works fine.

Resources