PortiBlog

Bulk restore items from the SharePoint recycle bin

6 februari 2019

When writing the blog https://www.mavention.nl/blogs-cat/paging-through-sharepoint-recycle-bin/ we ended with the conclusion that you can restore items in a recycle bin when the item limit threshold is exceeded. The solution provided required that the restore would take place as the user who deleted the items.

Before we executed the script on the customers production tenant, we did multiple successful tests on a development tenant. We did however not hit the threshold limit in there, we only tested the different scenarios with the accounts.

Before running the actual restore, we did test successfully a restore of an item removed by one of our own accounts. The problems occurred when we run the script with the user who had removed all items. Against our expectations we again where hit with threshold errors.

Item count in the recycle bin

I mentioned that the recycle bin did not show a count of items when it was exceeding the threshold. This turned out to not be the case. The counter only shows the items that you yourself removed. The user that removed the files we needed to restore had removed just over 110.000 items.

Working scenario without hitting the threshold

To verify the script, we created a temporary library, added 3 files and directly removed them. After this action the recycle bin had at least 110.003 items. We run the script with the paging from the previous blog article. After the script had finished, we had our 3 files back in the library. A second test had us adding and removing 3 items to the document library where all files were deleted from. This library contained near 120.000 items. Running the script was successful and we had our 3 files back.

Now it was time to contact the user and run the script to restore their approximately 110.000 removed items. Unfortunately, we received threshold errors on restoring the very first item.

Due to our test scenario’s we could conclude that the total amount of items in either the document library and the recycle bin where not the issue. On restoring, the number of items deleted by that specific user has an impact on the thresholds.

Working scenario when hitting the threshold

As we did not want to manually restore over 110.000 items, with 200 items per page if you would use the classic UI, we set out to search for another solution. As mentioned in the previous blog post, restoring items from the recycle bin itself works perfectly. If you have enough permissions, you can also restore items for other users from here.

As with figuring out how paging worked the developer tools came to the rescue here. We opened the developer tools in the modern UI. From here we selected a couple of items and hit the restore button. The network tab showed that the REST endpoint “site/RecycleBin/RestoreByIds” was used. In the body the ids of the items where passed on as an array.

Show me the code

We adapted our existing script that had the code to page through the recycle bin using CSOM and PowerShell. With that as a base we extended the script to use REST to restore the items. With some recursive functions we retrieved batches of 50 items to restore. We changed the code to only retrieve the ids of the items that needed to be restored. This gave us an array of 50 items at a time.
The first step to get it working was retrieving an authentication cookie to call the REST endpoint, we can retrieve that from the CSOM client context that we had to page through the recyle bin

$contextCredentials = $script:clientContext.Credentials
$authenticationCookies = $contextCredentials.GetAuthenticationCookie($script:fullSiteUrl, $true)

To make the requests via PowerShell we created a web request session to hold the cookies:

$webSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$webSession.Cookies.SetCookies($script:fullSiteUrl, $authenticationCookies)
$webSession.Headers.Add("Accept", "application/json;odata=verbose")

The next step we needed to have was a digest token, so the first call to make is one to the contextinfo endpoint, retrieve the digest token and add that to the headers of the websession

$response = Invoke-WebRequest -Uri "$($script:fullSiteUrl)/_api/contextinfo" -Method Post -WebSession $webSession
$responseJson = ConvertFrom-Json $response
$formDigest = $responseJson.d.GetContextWebInformation.FormDigestValue
$webSession.Headers.Add("X-RequestDigest", $formDigest);

This gave us all necessary items to perform the restore. We build a websession capable of authenticating the request and we had a collection of 50 items to restore. All we now need to do is call the RestoreByIds endpoint on the sites RecycleBin.

$url = "$($script:fullSiteUrl)/_api/site/RecycleBin/RestoreByIds"
$restoreCollection = ConvertTo-Json $script:itemsToRestore
$restoreCallContent = '{ "ids": ' + $restoreCollection + ' }'
$response = Invoke-WebRequest -Uri $url -Method Post -WebSession $webSession -Body $restoreCallContent -ContentType "application/json"

Conclusion

Restoring an item from the recycle bin in SharePoint can be done in several ways. Restoring items for a user that removed items far beyond the list item thresholds proves to be a challenge. Most documented endpoints will someway present you a threshold exceeded exception. Using a combination of techniques, in this case CSOM, REST and PowerShell, will save you a lot of time clicking through thousands of pages to restore all items.

Submit a comment