Recently I had to work on an issue where a user needed to migrate a list from one site collection to another in a different site collection. He used CSOM for this but was challenged by the fact that the list also contained several people and group columns which cannot just be copied over to the new site collection, as the users will have different lookup ids in each site collection.
It took me a couple of minutes to assemble the necessary lines of code which I would like to share with you as well in case you have a need to do something similar.
The code below has been simplified and copies only one people and group column to describe the concept. For a real world scenario you might want to add code enumerate the columns to copy all columns in the list.
using System.Collections.Generic;
using System.Net;
using System.Security.Principal;
using System.Security;
using Microsoft.SharePoint.Client;
namespace StefanG.Tools
{
class CopyPeopleColumn
{
// helper method to lookup a user in the user info list
static string LookupLoginNameInUserInfoList
(ClientContext context, int lookupId)
{
var username = string.Empty;
var userInfoList = context.Web.SiteUserInfoList;
context.Load(userInfoList);
ListItem item = userInfoList.GetItemById(lookupId);
context.Load(item);
context.ExecuteQuery();
loginName = item["Name"] as string;
return loginName;
}
static void Main(string[] args)
{
// add code to configure the credentials for SPO
string userid = …;
string pass = …;
// create the SecureString object for the password
SecureString password = new SecureString();
foreach (char a in pass) { password.AppendChar(a); }
// create the SPO credentials
ICredentials spoCred =
new Microsoft.SharePoint.Client.SharePointOnlineCredentials(userid,password);
// read people and groups field from source list
// create a client context to the source site collection using the
// credentials created earlier
ClientContext ctx = new ClientContext("https://url-to-source-site/");
ctx.Credentials = spoCred;
// get all the objects down to the list item we want to copy
Web web = ctx.Web;
ctx.Load(web);
List list = web.Lists.GetByTitle("Source List");
ctx.Load(list);
// for demo purposes I assume an item with Id 1 exists
ListItem item = list.GetItemById(1);
ctx.Load(item);
ctx.ExecuteQuery();
// read the user details from the people and group column
FieldUserValue fuv = (FieldUserValue)item["user_column"];
// use the lookup id to get the login name from the
// user information list of the source site collection
string loginName = LookupLoginNameInUserInfoList(ctx, fuv.LookupId);
// copy the content over to the new list
// create a cli
ent context to the target site collection using the
// credentials created earlier
ClientContext ctx2 = new ClientContext("https://url-to-target-site/");
ctx2.Credentials = spoCred;
// get all the objects down to the list we want to copy to
Web web2 = ctx2.Web;
ctx2.Load(web2);
List list2 = web2.Lists.GetByTitle("Workload Technology Contacts");
ctx2.Load(list2);
ctx2.ExecuteQuery();
// ensure that the user with the login name is populated into the
// user information list in the target site collection
User newUser = web2.EnsureUser(loginName);
ctx2.Load(newUser);
ctx2.ExecuteQuery();
// construct the value of the people or group column for the user
FieldUserValue newValue = new FieldUserValue();
newValue.LookupId = newUser.Id;
// create a new list item and assign field value
ListItem targetListItem = list2.AddItem(new ListItemCreationInformation());
targetListItem["user_column"] = newValue;
// write back to the target list
targetListItem.Update();
ctx2.ExecuteQuery();
}
}
}
Permalink
Very nice. Thank you, Stefan!
Permalink
Recently I had to work on an issue where a user needed to migrate a list from one site collection to
Permalink
Super article. Thank you very much. I actually was encountering this issue. THANK YOU VERY MUCH.
Permalink
Como estrenamos mes nuevo (en plenos carnavales :P), toca un nuevo recopilatorio de enlaces interesantes
Permalink
Thanks & Good Information Provide.
Permalink
thanks
Permalink
How about migrating legacy site collections with long-gone orphan users? Server-side PowerShell might suffice?