In an earlier blog post, I took a closer look at the CopyTo function that has been available in the Modern OneDrive and SharePoint experience for some time now. Whilst this was a definite improvement on the previous CopyTo functionality available in SharePoint, it was still a few steps short of what would be needed for true document lifecycle management.
The key issue with the CopyTo functionality is of course Duplication. If we create a document in our OneDrive and then publish this to a SharePoint team site to reach a wider audience, we need to go back and delete the source document to reduce duplication. And by using CopyTo and Delete in this manner, we lose the rich version history that SharePoint provides us.
With the release of the long awaited MoveTo functionality in the modern experience, Microsoft have now given us the means to implement a proper document lifecycle process, with the function copying not just the Document, but also the version history and where applicable the Metadata too (See the CopyTo blog post for more details about the metadata matching!).
If we select a document (or documents, MoveTo works with multiple documents, originally limited to 50 documents, it would appear that Microsoft have removed this limit as you’ll see in my testing shortly.), the MoveTo option now appears in both the context menu and the menu bar for the library. Clicking on this opens a sidebar as shown below.
The image on the left is the OneDrive Panel and the one on the right is from a SharePoint modern library, showing the same common experience across both OneDrive and SharePoint. The first option allows you to move content within the same OneDrive or Library, and the rest of the options allow you to select either your OneDrive (when in a SharePoint library) and other SharePoint sites.
But where does this list of sites come from? If we take a look at the calls made by the page through fiddler, we can see the API request made by the panel (This is from OneDrive)
GET /api/v1/sites/followed?acronyms=true&fillsitedata=true&mostRecentFirst=true&start=60&count=24
So we’re calling the Sites API and looking for the sites that we follow and showing the most recent of those sites first. If the site that we want to move the data to isn’t listed, we can click Browse Sites to see a different view.
This time we now see two separate views (And two separate API calls in fiddler), with followed sites at the top, along with a show more link and then the most recent sites at the bottom. (Interestingly I think there’s a bit of a zero indexing bug going on here as the API call asks for 5 sites, but 6 get returned!)
GET /api/v1/sites/followed?acronyms=true&fillsitedata=true&mostRecentFirst=true&start=0&count=5
GET /api/v1/sites/recent?acronyms=true&start=0&count=5
Clicking on Show More makes another API call for 5 more followed sites.
GET /api/v1/sites/followed?acronyms=true&fillsitedata=true&mostRecentFirst=true&start=5&count=5
If we select a site, we’ll see a call to
POST /sitenamehere/_api/SP.Web.GetDocumentLibraries?webFullUrl=’https%3A%2F%2Ftenantname%2Esharepoint%2Ecom%2Fsites%2FNoGroupTest’
And then a view of all of the available Document Libraries in the selected site.
Selecting a library makes one more call to the API to return a list of folders (filtering on FSObjType = 1 to represent folder)
POST /sitenamehere/_api/SP.List.GetListDataAsStream?listFullUrl=’https%3A%2F%2Ftenanename%2Esharepoint%2Ecom%2Fsites%2FNoGroupTest%2FMoveDestination’&View=&RootFolder=%2Fsites%2FNoGroupTest%2FMoveDestination&SortField=LinkFilename&SortDir=Asc&FilterField1=FSObjType&FilterValue1=1
And then displays a list of available folders, an option to create a folder (if the creation of folders is permitted in the library) and then the “Move here” button to confirm the selection.
If we finally click “Move here”, a single API call passes all 163 of our selected files, and we see a progress bar in the panel.
The API call is a fairly simple JSON construct going to
POST /sitename/_api/site/CreateCopyJobs HTTP/1.1
Which passes the following JSON structure
JSON:
- destinationUri: Destination library path
- exportObjectUris: An array of the path to each individual source item
- options: IgnoreVersionHistory and IsMoveMode
Then at regular intervals, we see calls to:
POST /personal/paul_hunt_wharfconsulting_co_uk/_api/$batch
Once completed, we’ll see a final status which tells us 4 files weren’t moved and the library view updates to show that the files have been removed from the source library. For some reason, I had 9 files that didn’t copy so I’m wondering if I hit a soft cap by trying to move 163 files at once, however when I checked the destination all 163 files copied successfully, so it looks like the deletes failed for these 9, with only 4 reporting errors to the UI.
Looking at the fiddler traces, I could see some JobWarnings coming back in the CopyJobProgress call, but there wasn’t any clear reason why these 9 files failed to copy. The warnings all related to metadata fields that failed to map. At this point I think I need to do some further testing with large numbers of documents, certainly for smaller numbers the MoveTo functionality works well and will hopefully be improved as the modern libraries are developed further.