Reading Time: 3 minutes

Always we have a limitation to copy the pages and Site Pages to another site

Issues

  1. Copy a page across different site collections
  2. Moving SharePoint Pages from one site to another
  3. Publishing feature enables site it is not supported to migrate root sites into sub sites or sub sites into root sites.
  4. Move the files, but not web parts
  5. etc…

Solution

I found a  solution for this issues using CSOM

My code migrate the Page/file, Metadata’s and Web parts.

Only one Limitation is we can’t migrate list view web parts, since list view web parts are not allowed to export and it is specified for the particular site.

Environment

  1. SharePoint/Office 365 SharePoint Online
  2. Visual Studio
  3. CSOM
  4. Also included the Lasted CSOM to migrate web parts –
    • New SharePoint CSOM version for SharePoint Online – June 2016 (Microsoft.SharePointOnline.CSOM )

Below code uses CSOM to copy all files/Pages, folders and Webpart from one Pages/Site Pages library to another Pages/Site Pages library.  This code will allow you to copy an entire Pages/Site Pages library, along with user-defined metadata from one site collection to another.

Pass the user credentials, source and destination site URL and Libraries. I have tested in office 365 SharePoint Online.

public void CloneSitePages(string srcUrl, string srcLibrary, string destUrl, string userName, SecureString pwd)
{

string srclibraryname = string.Empty;
string fileName = string.Empty;
string folderPath = string.Empty;
int id = 0;
try
{

ClientContext srcContext = new ClientContext(srcUrl);
ClientContext destContext = new ClientContext(destUrl);

srcContext.Credentials = new SharePointOnlineCredentials(userName, pwd);
srcContext.RequestTimeout = Timeout.Infinite;
Web srcWeb = srcContext.Web;
List srcList = srcWeb.Lists.GetByTitle(srcLibrary);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = “<View Scope=’RecursiveAll’></View>”;
ListItemCollection itemColl = srcList.GetItems(camlQuery);
srcContext.Load(itemColl);
OSP.FieldCollection fields = srcList.Fields;
srcContext.Load(fields);
srcContext.ExecuteQuery();

destContext.Credentials = new SharePointOnlineCredentials(userName, pwd);
destContext.RequestTimeout = Timeout.Infinite;
Web destWeb = destContext.Web;
destContext.Load(destWeb);
destContext.ExecuteQuery();

string _path = destWeb.ServerRelativeUrl;
if (itemColl.Count > 0)
{

srclibraryname = itemColl[0].FieldValues[“FileDirRef”].ToString();
string[] srcurlSplit = srclibraryname.Split(‘/’);
srclibraryname = srcurlSplit[srcurlSplit.Count() – 1];

foreach (ListItem doc in itemColl)
{
if (doc.FileSystemObjectType == FileSystemObjectType.File)
{
fileName = doc[“FileRef”].ToString();
string[] fileNames = fileName.Split(new string[] { srclibraryname }, StringSplitOptions.None);
fileName = fileNames[fileNames.Count() – 1];

OSP.File file = doc.File;
srcContext.Load(file);
srcContext.ExecuteQuery();

FileInformation fileInfo = OSP.File.OpenBinaryDirect(srcContext, file.ServerRelativeUrl);

string serverRelevantUrl = _path + “/” + srclibraryname + fileName;
Microsoft.SharePoint.Client.File.SaveBinaryDirect(destContext, serverRelevantUrl, fileInfo.Stream, true);
Microsoft.SharePoint.Client.File spfile = destContext.Web.GetFileByServerRelativeUrl(serverRelevantUrl);
ListItem item = spfile.ListItemAllFields;
destContext.Load(item);
destContext.ExecuteQuery();
id = item.Id;

//Get all webparts from the page
OSP.WebParts.LimitedWebPartManager limitedWebPartManager = file.GetLimitedWebPartManager(OSP.WebParts.PersonalizationScope.Shared);
srcContext.Load(limitedWebPartManager.WebParts, f => f.Include(s => s.WebPart.Properties, s => s.WebPart.Title, s => s.WebPart.ZoneIndex, s => s.Id));
srcContext.ExecuteQuery();

if (limitedWebPartManager.WebParts.Count > 0)
{
for (int w = 0; w < limitedWebPartManager.WebParts.Count; w++)
{
OSP.WebParts.WebPartDefinition oWebPartDefinition = limitedWebPartManager.WebParts[w];
OSP.WebParts.WebPart oWebPart = oWebPartDefinition.WebPart;
OSP.PropertyValues props = oWebPart.Properties;

string ExportMode = oWebPartDefinition.WebPart.Properties.FieldValues[“ExportMode”].ToString();
//foreach (KeyValuePair<string, object> field in props.FieldValues.ToList())
//{
// if (field.Key == “ExportMode”)
// {
// ExportMode = field.Value.ToString();
// break;
// }
//}
if (ExportMode == “1”)
{

ClientResult<string> webPartXmlData = limitedWebPartManager.ExportWebPart(oWebPartDefinition.Id);
srcContext.Load(oWebPartDefinition, f => f.ZoneId);
srcContext.ExecuteQuery();
var webPartXml = webPartXmlData.Value;

var page = destContext.Web.GetFileByServerRelativeUrl(serverRelevantUrl);
OSP.WebParts.LimitedWebPartManager deslimitedWebPartManager = page.GetLimitedWebPartManager(OSP.WebParts.PersonalizationScope.Shared);
OSP.WebParts.WebPartDefinition desWebPartDefinition = deslimitedWebPartManager.ImportWebPart(webPartXml);
if (oWebPartDefinition.ZoneId == “wpz”)
{

OSP.WebParts.WebPartDefinition newWebPartDefinition = deslimitedWebPartManager.AddWebPart(desWebPartDefinition.WebPart, “Header”, oWebPartDefinition.WebPart.ZoneIndex);

}
else
{

OSP.WebParts.WebPartDefinition newWebPartDefinition = deslimitedWebPartManager.AddWebPart(desWebPartDefinition.WebPart, oWebPartDefinition.ZoneId, oWebPartDefinition.WebPart.ZoneIndex);

}
destContext.ExecuteQuery();
}
}

}
//Console.WriteLine(“Webparts Added”);

//update the properties to the current page
OSP.List oList = destContext.Web.Lists.GetByTitle(srcLibrary);
ListItem oListItem = oList.GetItemById(id);

for (int i = 0; i < fields.Count; i++)
{

OSP.Field fieldTemp = fields[i];
string InternalName = fieldTemp.InternalName;
if ((!fieldTemp.ReadOnlyField) && (fieldTemp.InternalName != “Attachments”) && (fieldTemp.InternalName != “ContentType”))
{
oListItem[InternalName] = doc[InternalName];
}

}

oListItem.Update();
destContext.ExecuteQuery();

//Publish the page
if (targetPublish)
{

oListItem.File.CheckIn(“Migrated”, CheckinType.MajorCheckIn);
oListItem.File.Publish(“Migrated”);
destContext.ExecuteQuery();

}
}
else if (doc.FileSystemObjectType == FileSystemObjectType.Folder)
{

folderPath = doc[“FileRef”].ToString();
string[] fileNames = folderPath.Split(new string[] { srclibraryname }, StringSplitOptions.None);
folderPath = fileNames[fileNames.Count() – 1];
folderPath = folderPath.TrimStart(new Char[] { ‘/’ });
var folder = CreateFolder(destContext.Web, srcLibrary, folderPath);

}

}

}

}
catch (Exception ex)
{

Console.WriteLine(ex.Message);

}

}

Folder Creation

public OSP.Folder CreateFolder(Web web, string listTitle, string fullFolderPath)
{

if (string.IsNullOrEmpty(fullFolderPath))
throw new ArgumentNullException(“fullFolderPath”);
var list = web.Lists.GetByTitle(listTitle);
return CreateFolderInternal(web, list.RootFolder, fullFolderPath);

}

private OSP.Folder CreateFolderInternal(Web web, OSP.Folder parentFolder, string fullFolderPath)
{

var folderUrls = fullFolderPath.Split(new char[] { ‘/’ }, StringSplitOptions.RemoveEmptyEntries);
string folderUrl = folderUrls[0];
var curFolder = parentFolder.Folders.Add(folderUrl);
web.Context.Load(curFolder);
web.Context.ExecuteQuery();

if (folderUrls.Length > 1)
{
var folderPath = string.Join(“/”, folderUrls, 1, folderUrls.Length – 1);
return CreateFolderInternal(web, curFolder, folderPath);
}

return curFolder;
}

Good luck

Also I built a Site Provisioning and Migration tool, please download and use it for all migrations. http://jenkinsblogs.com/sharepoint-migration-tool-free/

If you looking for code https://siteprovisioning.codeplex.com/