Backup and Restore Site Collection with Managed Navigation
Managed navigation in SharePoint allows you to define SEO friendly URLs to SharePoint pages. This feature helps your visitors remember the URLs and also increases your page ranking in search engines. Once you enable the managed navigation for your site, SharePoint relates every page with a navigation term. To understand more about managed navigation, find the MSDN link
https://msdn.microsoft.com/en-us/library/office/jj163978.aspx
In this article, I am going to explain how you can restore site collections that uses managed navigation from one farm to different farm. This is important as when you are working on a project you need to deal with several environments. You will have a development environment where your team actually work on, a testing environment where users ensure the functionality/content is right before showing to customer, a staging environment where the customer checks the site before going live and finally a production environment. It is obvious that you need to move site from one environment to another frequently, probably in the below order.
development -> test -> staging -> production
Assumptions
For the purpose of this article, I am assuming you have two SharePoint 2016 farms namely source farm and destination farm. You have a site collection available in the source farm with managed navigation.
I also assume you already restored site collection in the destination farm. Backup/Restore of site collections is not the topic of this article, however if you wish to read more about backup/restore in SharePoint, refer my article
https://weblogs.asp.net/sreejukg/backup-and-restore-in-sharepoint-2010-using-powershell
To visualize the scenario where we are going to start from, refer the below image.
Step 1 : Backup the MMS Database from the source farm
First thing you need to do is to take a backup of your managed navigation instance database from the source farm. From the source farm, open SharePoint management shell. First get the the GUID of the managed meta data service instance. Execute the following PowerShell command
Get-SPServiceInstance
See the output of the command in my test environment.
In order to take the backup of your meta data service database, you need to stop the service instance of your managed meta data service. To stop your managed meta data service instance, execute the following command, make sure to use the GUID from your environment.
Stop-SPServiceInstance -Identity a6325294-0c81-4dde-b4ba-f55c90e6b4c0
See the output of the command, you need to Press Y to confirm.
Ensure that the service instance status is disabled. You can use Get-SPServiceInstance command and ensure the service is disabled.
Once the metadata service is stopped, you can detach the database and copy the mdf & ldf files of your database. By default, you will be able to locate the meta data service instance from the SQL Server management studio by the name of the database. If you have many databases, you can use the following command to find out the meta data service application database.
Get-SPDatabase | Where {$_.Type -like "*MetadataWebService*"} | Select Name
See the output of the command as below.
Now open SQL Server management studio, and expand the databases node and locate your managed metadata service database.
Right click the instance database and select tasks –> Detach
Click OK. Now you can copy the mdf /ldf files of your database from the data directory.
Once you copy the database files and keep it in a separate location, you need to use attach database command to attach the database back to your source farm. From the management studio, right click the databases node and select attach database, and then select the mdf file you detached just now. Once the database is attached, you need to start the service instance. Use the below command to start the meta data service instance, make sure you use GUID from your environment.
Start-SPServiceInstance -Identity bd7f2678-4569-472b-90a5-a11b44bd9e68
With this you have done the steps in the source server.
Step 2: Restore Metadata database to the destination farm
You need to copy the mdf & ldf files to the destination database server, ideally in the data folder of your destination server.
In the SQL Server Management Studio of the destination farm, Right click the databases node, and select Attach
In the attach databases dialog, select the mdf file you copied from the source farm.
Note: You can rename the file names or database name as you wish, for the purpose of this demonstration, I renamed the attached database to “MMS_DB”
Step 3: Set the restored databases as the metadata service application database in the destination farm
Now you need to set the metadata service application database in the destination farm to the newly restored database. Open SharePoint Command Shell in the destination farm execute the following command.
$app = Get-SPServiceApplication -Name "Managed Metadata Service"
Set-SPMetadataServiceApplication -Identity $app -DatabaseName "MMS_DB"
Note: In the above command you need the name your metadata service application. The following power shell script will help you find the service application names of all service applications.
Get-SPServiceApplication | Select Name
Once you set the database, you may want to ensure whether the database is updated. Run the below PowerShell scripts so that you will get the database name.
$app = Get-SPServiceApplication -Name "Managed Metadata Service"
$app | Select Database
Let us recollect what we have done so far, we restored the MMS database to the destination farm and set it as the service application database.
Step 4: Associate Site Collection and Sites to Term Store
The restored database contains the term set and terms from the source site collection. The terms are associated to pages and the term set is associated to the site collection. The association is maintained by using the ids of site collection and terms/termsets. But when you restore the site collection, the restored site collection will have a new ID and now all the associations are broken. We need to re-associate sites and subsites to the term store.
In order to associate, you need to find the term set you were using. Open the restored database in SQL Server management studio, open new query window and execute the following query.
select * from ecmgroup
You need to copy the UniqueId of the term set of your site collection.
Let me explain how a site collection or sub site is associated with the term set. The site collection rootWeb has a property as below.
SiteCollectionGroupId<TermStoreID>
The <TermStoreID> is the id of the default site collection term store. The value of the property will be the uniqueID you found from the previous SQL Query.
e.g.
Property Name
Value
SiteCollectionGroupId42c2d963-0fda-48ac-9762-49206d171a13
E063ACFA-1A83-4E6E-82DF-66C36459016A
Once you add the property, you need to use the AddSiteCollectionAccess Method of the term store group to grant the permission for the site collection to the group.
The below PowerShell script will do this, you need to use the uniqueID from the SQL query as the groupID and your site URL.
#Function definition to associate the termstore to site Collection
function AssociateSiteCollectionToTermStore($site, $groupId)
{
$tx = New-Object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)
$termstore =$tx.DefaultSiteCollectionTermStore
$termStoreId = $termstore.Id
$SiteCollectionTermStorePropertyName = "SiteCollectionGroupId" + $termStoreId
$web = $site.RootWeb
$webProp = $web.GetProperty($SiteCollectionTermStorePropertyName)
If ($webProp –eq $null)
{
$web.AddProperty($SiteCollectionTermStorePropertyName , $groupId )
}
Else
{
# Property exists – remove/re-add the property
$web.DeleteProperty($SiteCollectionTermStorePropertyName)
$web.AddProperty($SiteCollectionTermStorePropertyName , $groupId )
}
$web.Update()
$group = $termstore.Groups | Where-Object {$_.id –eq $groupId}
$group.AddSiteCollectionAccess($site.id)
$termstore.CommitAll()
}
$site = Get-SPSite <Your Site URL>
$groupId = "E063ACFA-1A83-4E6E-82DF-66C36459016A" #The UniqueId from the SQL query
AssociateSiteCollectionToTermStore $site $groupId
Step 5: Associate Site Collection and Sites to Term Store
Now if you go to the term store, you will find the terms, but still you will find the friendly URLs will not work!. You need to update the permissions! Now the terms owner is owned by the source farm user. Typically your different environments are under different active directory, so you need to modify the owner of each term.
The below PowerShell script will help you to set the owner of all termset in the termstore.
#Update Owner function
function UpdateTermOwner($site, $newOwner, $groupId)
{
$tx = New-Object Microsoft.SharePoint.Taxonomy.TaxonomySession($site)
$termstore =$tx.DefaultSiteCollectionTermStore
foreach($admin in $termstore.TermStoreAdministrators)
{
#Delete the existing owner first
Write-Host ([String]::Format("Removing User {0} from TermStore Administrators",$admin.PrincipalName)) -foregroundcolor blue
$termStore.DeleteTermStoreAdministrator($admin.PrincipalName);
}
#Adding new term Store Administrator
Write-Host ([String]::Format("Adding User {0} as TermStore Administrator",$newOwner)) -foregroundcolor green
#$termStore.AddTermStoreAdministrator($newOwner);
$group = $termstore.Groups | Where-Object {$_.id –eq $groupId}
foreach($termSet in $group.TermSets)
{
Write-Host ([String]::Format("Adding User {0} as Owner",$newOwner)) -foregroundcolor green
#$termSet.Owner = $newOwner
}
$termStore.CommitAll();
}
$site = Get-SPSite <Your Site URL>
$newOwner = "Domain\user"
$groupId = "E063ACFA-1A83-4E6E-82DF-66C36459016A"
UpdateTermOwner $site $newOwner $groupId
Step 6: Update the Navigation Source to Taxonomy Provider for all your Sites
After completing the step 5, I was in the impression that the terms must be mapped to the sites correctly. But the friendly URLs were note working yet, I found if I got to any site and just modify the navigation property and save it, the friendly URLs starts working. So, you need to traverse through all your sub sites and update your navigation. The below PowerShell Script just perform this.
Now you have access to the terms. You need to update the navigation
# Fix the Navitation
function FixNavigation($url)
{
try
{
$web = Get-SPWeb $url;
Write-Host ([String]::Format("Procesing web {0}",$web.Url)) -foregroundcolor White
WebNavSettings = New-Object Microsoft.SharePoint.Publishing.Navigation.WebNavigationSettings($Web);
$WebNavSettings.GlobalNavigation.Source = "PortalProvider"
$WebNavSettings.CurrentNavigation.Source = "PortalProvider"
$WebNavSettings.Update()
Write-Host ([String]::Format("Updated navigation to Structured {0}",$web.Url)) -foregroundcolor blue
$web = Get-SPWeb $url;
$WebNavSettings = New-Object Microsoft.SharePoint.Publishing.Navigation.WebNavigationSettings($Web);
$WebNavSettings.GlobalNavigation.Source = "TaxonomyProvider"
$WebNavSettings.CurrentNavigation.Source = "TaxonomyProvider"
$WebNavSettings.Update()
Write-Host ([String]::Format("Updated navigation to Structured {0}",$web.Url)) -foregroundcolor green
if($web.Webs.Count -gt 0)
{
foreach($subWeb in $web.Webs)
{
#$web.Url
FixNavigation $subWeb.Url;
}
}
}
catch
{
Write-Host ([String]::Format("Error processing web at $url, with Exception: {0}", $_.Exception.Message)) -foregroundcolor Red
}
}
$url = <Your Site URL>
FixNavigation($url)
Summary
I tested these steps in couple of environments and it worked. Use the comment area below to post your experience. Enjoy!