How to perform CRUD operations on a CROSS DOMAIN SharePoint
2013/2016 List from JavaScript using REST API. My target and source farms are
within the Organization hence it does not cover the scenario where SharePoint
Online is involved.
Recently I had a requirement to write data on a SharePoint
List that resides on a separate SharePoint farm, I was asked to do this without
writing Apps and possibly using JavaScript.
Initially I thought it’s a simple task and will not take
more than a few minutes however I proved wrong very quickly. It is tricky and
not much end to end help is available on line hence I thought of writing this
blog.
Business Requirement:
I have a list named “oAuthTestList” in http://sharepointtesting.xxxx.com/xxxx/SharePoint/oAuth
and I should be able to write into this list from a Page that is
residing on a different SharePoint Farm http://sharepointdev.xxxx.com/sand/xxxx.
The Page can have a Content Editor Web Part or Script Editor but now
Server Side code.
For this example I am assuming that SharePoint URLs for
Source and Target Farms are as following:
Source Farm: http://sharepointdev.xxxx.com/sand/xxxx
I am also assuming that you have created a OAuthTest List in
Target Farm. It has only one default column named as “Title”. Make sure you
also make “ID” column visible on this list by modifying its default view. So
now your list should show “ID” and “Title” columns.
Notice the first part of urls “sharepointdev” and “sharepointtesting”,
it makes difficult to perform CRUD operations as SharePoint considers them as
Cross Domain calls.
I have following two solutions to go without writing an app:
- Using CSOM
- Using REST API
Following is quick examples how to use both of them.
a.
I created a HTML File and a JavaScript File and
placed them into SiteAssets document library in Source Farm (i.e. http://sharepointdev.xxxx.com/sand/xxxx
).
b.
I created a JavaScript file and name it as CSOMCreateAnItemInSharePointList.js.
Following is its code.
function PerformListOperations() {
var clientContext = new SP.ClientContext( "http://sharepointtesting.xxxx.com/teams/SharePoint" );
var oList =
clientContext.get_web().get_lists().getByTitle('OAuthTest');
var itemCreateInfo = new SP.ListItemCreationInformation();
this.oListItem = oList.addItem( itemCreateInfo );
oListItem.set_item('Title',$('#Title').val());
oListItem.update();
clientContext.load(oListItem);
clientContext.executeQueryAsync(onPerformListOperationsSuccess, onPerformListOperationsFail);
}
function onPerformListOperationsSuccess() {
alert("Successfully created an item using
CSOM...");
}
function onPerformListOperationsFail(sender, args) {
alert('Failed to create. Error:' + args.get_message());
}
$(document).ready(function () {
$("#CreateButton").click(function () {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', PerformListOperations);
});
});
c.
I created an html page and named it as “CSOMCreateAnItemInSharePointList.html”.
Following is its code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="http://sharepointdev.xxxx.com/xxxx/SiteAssets/CSOMCreateAnItemInSharePointList.js"></script>
<script src="oAuthCreateOAuthTest.js"></script>
</head>
<body>
<div id="ListContainer"></div>
<table>
<tr>
<td>Title:</td>
<td><input id="Title" type="textbox" value="Type new title
text here"/></td>
</tr>
<tr>
<td><input id="CreateButton" type="button" value="Create" /></td>
</tr>
</table>
</body>
</html>
d. Copy both the files in SiteAssets
document library on Source SharePoint Farm.
e. Now add a SharePoint Web Part Page on
Source SharePoint Farm and add a Content Editor Web Part and configure the Path
of CSOMCreateAnItemInSharePointList.html as created above.
f. That’s all now you can add a list item
by providing title’s text value. Each time you click on Button it will add a
new item in the List.
2. Using REST API
a. It’s the tricky part and I used this
for my solution.
b. Again I created one HTML file and
named it as “oAuthCreateOAuthTest.html” with following code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link rel="stylesheet" href="/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="http://sharepointdev.xxxx.com/sand/xxxx/SiteAssets/oAuthCreateOAuthTest.js"></script>
<script src="oAuthCreateOAuthTest.js"></script>
</head>
<body>
<div id="ListContainer"></div>
<table>
<thead>
<tr>
<td>Item ID (leave as it
is for "Create"):</td>
<td><input id="ItemId" type="textbox" value="1"/></td>
</tr>
<tr>
<td>New Title Value :</td>
<td><input id="newTitle" type="textbox" value="Type New
Title"/></td>
</tr>
<tr>
<td><input id="CreateButton" type="button" value="Create" /></td>
<td><input id="UpdateButton" type="button" value="Update" /></td>
</tr>
</thead>
</table>
</body>
</html>
c. And I created on JavaScript file named as oAuthCreateOAuthTest.js.
Following is its code.
var
_listItems=[],
_options = {
listName: "oAuthTestList",
container: "#ListContainer"
};
function
WriteListDataToHtml(data, listName) {
_listItems = data.d.results;
var table = $("<table
style='width: 60%;'>" +
"<tr style='color: maroon;background-color:
yellow;font-weight:bold;'>" +
"<th>ID</th>" +
"<th>Date</th>" +
"<th>Title</th>" +
"</tr>" +
"</table>");
$.each(_listItems, function (index, item)
{
var tr = '<tr>' +
'<td>' + item.ID + '</td>' +
'<td>' + item.Created + '</td>' +
'<td>' + item.Title + '</td>' +
'</tr>';
table.append(tr);
});
$(_options.container).html(table);
}
function
AddListItem(formDigestValue,appUrl, newTitle)
{
var jsonMetaData = { __metadata: { type: 'SP.Data.OAuthTestListListItem' }, Title:
newTitle };
$.support.cors = true;
$.ajax({
url: appUrl,
type: "POST",
contentType: "application/json;odata=verbose",
headers: { "accept": "application/json;odata=verbose", "x-requestdigest": formDigestValue, "If-Match": "*" },
data: JSON.stringify(jsonMetaData),
xhrFields: { withCredentials: true },
success: function (data) {
if (data.d) {
RenderListData();
}
},
error: function (xhr) {
alert(xhr.status + ': ' +
xhr.statusText);
}
});
}
function
ReadListItem(formDigestValue, appUrl, newTitle) {
var jsonMetaData = { __metadata: { type: 'SP.Data.OAuthTestListListItem' }};
$.support.cors = true;
//items?$filter='Internal Name of the column' eq "Some
value"
$.ajax({
url: appUrl,
type: "GET",
contentType: "application/json;odata=verbose",
headers: { "accept": "application/json;odata=verbose"},
xhrFields: { withCredentials: true },
success: function (data) {
if (data.d) {
UpdateListItem(data.d.__metadata.etag, formDigestValue, appUrl,
newTitle);
}
},
error: function (xhr) {
alert(xhr.status + ': ' +
xhr.statusText);
}
});
}
function
UpdateListItem(etag, formDigestValue, appUrl, newTitle) {
var jsonMetaData = { __metadata: { type: 'SP.Data.OAuthTestListListItem' }, Title:
newTitle };
$.support.cors = true;
$.ajax({
url: appUrl,
type: "POST",
contentType: "application/json;odata=verbose",
headers: { "accept": "application/json;odata=verbose", "X-Http-Method": "MERGE", "x-requestdigest": formDigestValue, "If-Match": etag},
data: JSON.stringify(jsonMetaData),
xhrFields: { withCredentials: true },
success: function (data) {
alert("Successful");
RenderListData();
},
error: function (xhr) {
alert(xhr.status + ': ' +
xhr.statusText);
}
});
}
function
UpdateAListItem(listName, itemId, newTitle) {
var formDigest;
var hostUrl = "http://sharepointtesting.xxxx.com/xxxx/SharePoint/oAuth";
var appUrl = hostUrl+"/_api/web/lists/getbytitle('"+_options.listName+"')/items("+itemId+")";
$.support.cors = true;
$.ajax(
{
url:hostUrl + "/_api/contextinfo",
type: 'POST',
xhrFields: { withCredentials: true },
dataType:"json",
contentType: "application/x-www-url-encoded",
headers: {
"accept": "application/json;odata=verbose"
},
success: function (data) {
if(data.d){
formDigest =
data.d.GetContextWebInformation.FormDigestValue;
ReadListItem(formDigest, appUrl,
newTitle);
}
},
error: function (err) {
alert(xhr.status + ': ' + xhr.statusText);
}
});
}
function
CreateAListItem(listName, newTitle) {
var formDigest;
var hostUrl = "http://sharepointtesting.xxxx.com/xxxx/SharePoint/oAuth";
var appUrl = hostUrl + "/_api/web/lists/getbytitle('" + _options.listName + "')/items";
$.support.cors = true;
$.ajax(
{
url: hostUrl + "/_api/contextinfo",
type: 'POST',
xhrFields: { withCredentials: true },
dataType: "json",
contentType: "application/x-www-url-encoded",
headers: {
"accept": "application/json;odata=verbose"
},
success: function (data) {
if (data.d) {
formDigest =
data.d.GetContextWebInformation.FormDigestValue;
AddListItem(formDigest, appUrl,
newTitle);
}
},
error: function (err) {
alert(xhr.status + ': ' + xhr.statusText);
}
});
}
function RenderListData() {
var hostUrl = "http://sharepointtesting.xxxx.com/xxxx/SharePoint/oAuthh";
var appUrl = hostUrl + "/_api/web/lists/getbytitle('" + _options.listName + "')/items?$select=ID,Title,Created&$top=20&$orderby=Created
desc";
$.ajax(
{
type: "GET",
contentType: "application/json;
charset=utf-8",
url: appUrl,
xhrFields: { withCredentials: true },
processData: false,
dataType: "json",
headers: {
"Accept": "application/json; odata=verbose"
},
success: function (data) {
WriteListDataToHtml(data, _options.listName); },
error: function (error) {
console.log("Error in getting List: " + _options.listName);
$(_options.container).html("Error
retrieving your " + _options.listName + ".");
}
});
}
$(document).ready(function () {
$("#UpdateButton").click(function () {
var itemId = $("#ItemId").val();
var newTitle = $("#newTitle").val();
UpdateAListItem(_options.listName, itemId, newTitle);
});
$("#CreateButton").click(function () {
var itemId = $("#ItemId").val();
var newTitle = $("#newTitle").val();
CreateAListItem(_options.listName, newTitle);
});
RenderListData();
});
d.
Place both the files (oAuthCreateOAuthTest.html
and oAuthCreateOAuthTest.js) in “SiteAssets” document library in source
SharePoint Farm.
e.
Now let’s create a SharePoint Page in the source
SharePoint Farm and add a Content Editor web part. Configure the URL of oAuthCreateOAuthTest.html.
f.
Now you are ready to perform CRUD operations
from a SharePoint Farm’s page to a List located on the Target SharePoint Farm.
g.
Please note it will work only on Internet
Explorer.