Consuming the SharePoint 2013 REST API from PowerShell

Introduction

SharePoint 2013 introduces a Representational State Transfer (REST) service that is comparable to the  SharePoint CSOM and in addition to CSOM, REST API opens up a huge capabilities, in particular for administering and automating SharePoint Online when used with PowerShell.

Sending  REST requests to a SharePoint Online 

In the previous post we’ve already covered how to perform read operations by sending HTTPS requests to SharePoint RESTful web services. This time we are going to extend PowerShell script  in order to support all the CRUD operations.

The Invoke-RestSPO function sends  HTTPS requests to SharePoint REST web services that returns richly structured data (JSON)

Add-Type –Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type –Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
<#
.Synopsis
Sends an HTTP or HTTPS request to a SharePoint Online REST-compliant web service.
.DESCRIPTION
This function sends an HTTP or HTTPS request to a Representational State
Transfer (REST)-compliant ("RESTful") SharePoint Online web service.
.EXAMPLE
Invoke-SPORestMethod -Url "https://contoso.sharepoint.com/_api/web&quot;
.EXAMPLE
Invoke-SPORestMethod -Url "https://contoso.sharepoint.com/_api/contextinfo&quot; -Method "Post"
#>
Function Invoke-RestSPO(){
Param(
[Parameter(Mandatory=$True)]
[String]$Url,
[Parameter(Mandatory=$False)]
[Microsoft.PowerShell.Commands.WebRequestMethod]$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password,
[Parameter(Mandatory=$False)]
[String]$Metadata,
[Parameter(Mandatory=$False)]
[System.Byte[]]$Body,
[Parameter(Mandatory=$False)]
[String]$RequestDigest,
[Parameter(Mandatory=$False)]
[String]$ETag,
[Parameter(Mandatory=$False)]
[String]$XHTTPMethod,
[Parameter(Mandatory=$False)]
[System.String]$Accept = "application/json;odata=verbose",
[Parameter(Mandatory=$False)]
[String]$ContentType = "application/json;odata=verbose",
[Parameter(Mandatory=$False)]
[Boolean]$BinaryStringResponseBody = $False
)
if([string]::IsNullOrEmpty($Password)) {
$SecurePassword = Read-Host Prompt "Enter the password" AsSecureString
}
else {
$SecurePassword = $Password | ConvertTo-SecureString AsPlainText Force
}
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$request = [System.Net.WebRequest]::Create($Url)
$request.Credentials = $credentials
$request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
$request.ContentType = $ContentType
$request.Accept = $Accept
$request.Method=$Method
if($RequestDigest) {
$request.Headers.Add("X-RequestDigest", $RequestDigest)
}
if($ETag) {
$request.Headers.Add("If-Match", $ETag)
}
if($XHTTPMethod) {
$request.Headers.Add("X-HTTP-Method", $XHTTPMethod)
}
if($Metadata -or $Body) {
if($Metadata) {
$Body = [byte[]][char[]]$Metadata
}
$request.ContentLength = $Body.Length
$stream = $request.GetRequestStream()
$stream.Write($Body, 0, $Body.Length)
}
else {
$request.ContentLength = 0
}
#Process Response
$response = $request.GetResponse()
try {
if($BinaryStringResponseBody -eq $False) {
$streamReader = New-Object System.IO.StreamReader $response.GetResponseStream()
try {
$data=$streamReader.ReadToEnd()
$results = $data | ConvertFrom-Json
$results.d
}
finally {
$streamReader.Dispose()
}
}
else {
$dataStream = New-Object System.IO.MemoryStream
try {
StreamCopyTo Source $response.GetResponseStream() Destination $dataStream
$dataStream.ToArray()
}
finally {
$dataStream.Dispose()
}
}
}
finally {
$response.Dispose()
}
}
# Get Context Info
Function Get-SPOContextInfo(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password
)
$Url = $WebUrl + "/_api/contextinfo"
Invoke-RestSPO $Url Post $UserName $Password
}
Function Stream-CopyTo([System.IO.Stream]$Source, [System.IO.Stream]$Destination)
{
$buffer = New-Object Byte[] 8192
$bytesRead = 0
while (($bytesRead = $Source.Read($buffer, 0, $buffer.Length)) -gt 0)
{
$Destination.Write($buffer, 0, $bytesRead)
}
}

view raw
Invoke-RestSPO.ps1
hosted with ❤ by GitHub

Request Digests

Since SharePoint requires the user to include a request digest value with each create, update and delete operation, an additional request is invoked using Get-SPOContextInfo function to request Context Info entity that contains request digest value.

 ETag

In order to avoid an additional request, “*” eTag value is used to match any eTag value resulting in the operation being performed regardless of the actual value.

Lists manipulation using REST API in PowerShell

This section contains sample code for all of the CRUD operations.

#———————————————————————————————-
# List CRUD operations via SharePoint REST API
#———————————————————————————————-
# Create a List
Function New-SPOList(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password,
[Parameter(Mandatory=$True)]
[String]$Title,
[Parameter(Mandatory=$True)]
[String]$BaseTemplate
)
$listMetadata = @{
__metadata = @{'type' = 'SP.List' };
Title = $Title;
BaseTemplate = $BaseTemplate} | ConvertTo-Json
$Url = $WebUrl + "/_api/lists"
$contextInfo = Get-SPOContextInfo $WebUrl $UserName $Password
Invoke-RestSPO $Url Post $UserName $Password $listMetadata $contextInfo.GetContextWebInformation.FormDigestValue
}
# Update a List
Function Set-SPOList(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password,
[Parameter(Mandatory=$True)]
[String]$Identity,
[Parameter(Mandatory=$False)]
[String]$Title,
[Parameter(Mandatory=$False)]
[String]$Description
)
$listMetadata = @{
__metadata = @{'type' = 'SP.List' };
}
if($Title) {
$listMetadata['Title'] = $Title
}
if($Description) {
$listMetadata['Description'] = $Description
}
$listMetadata = $listMetadata | ConvertTo-Json
$Url = $WebUrl + "/_api/lists/getbytitle('" + $Identity + "')"
$contextInfo = Get-SPOContextInfo $WebUrl $UserName $Password
Invoke-RestSPO Url $Url Method Post UserName $UserName Password $Password RequestDigest $contextInfo.GetContextWebInformation.FormDigestValue Metadata $listMetadata ETag "*" XHTTPMethod "MERGE"
}
#Get List(s)
Function Get-SPOList(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password
)
$Url = $WebUrl + "/_api/lists"
$data = Invoke-RestSPO $Url Get $UserName $Password
$data.results
}
#Delete a List
Function Remove-SPOList(){
Param(
[Parameter(Mandatory=$True)]
[String]$WebUrl,
[Parameter(Mandatory=$True)]
[String]$UserName,
[Parameter(Mandatory=$False)]
[String]$Password,
[Parameter(Mandatory=$True)]
[String]$Identity
)
$Url = $WebUrl + "/_api/lists/getbytitle('" + $Identity + "')"
$contextInfo = Get-SPOContextInfo $WebUrl $UserName $Password
Invoke-RestSPO Url $Url Method Post UserName $UserName Password $Password RequestDigest $contextInfo.GetContextWebInformation.FormDigestValue ETag "*" XHTTPMethod "DELETE"
}

view raw
ListOps-RestSPO.ps1
hosted with ❤ by GitHub

References