Replicate SharePoint Hub site navigation to other Hub sites

I have been working with a large government department where Microsoft Services helped them transform their intranet to SharePoint Online leveraging all the modern capabilities available as well as rethinking what an intranet was. This work included envisioning to fully exploit all of Office 365 and a crucial Information Architecture (IA) design which also mapped their existing, complex and poorly performing hierarchy of subsites to several new hub sites and a completely flattened site structure. I hope to write more about this work soon.

Primary intranet site navigation provider

To create a consistent user experience, the look and feel for several hub sites was replicated, creating the feel of a single intranet. The hub site navigation also needed to be replicated, and that is wherein the challenge lay. The navigation cannot be easily copied from one site to another, let alone between hub sites, and thus this solution was born.

We decided to create a dedicated hub site that only the intranet team can access. Within this hub site, we were then able to create the intended intranet navigation and get the headings, order and links just right without troubling anyone. Once we were happy with the navigation and testing successfully passed, the idea was that we would be able to replicate the hub site navigation to all our other hub sites. More importantly, the process could be easily repeated, keeping the intranet navigation updated across many hub sites. The task could also be automated but we opted to leave it as a manually initiated task.

Script to replication hub site navigation to other sites

The solution to the problem is a PowerShell script made up of two functions. One function that gets the navigation from the hub site acting as the master or primary navigation provider (supplied from a parameter). The other function replicates the navigation to other hub sites. The Get-SPOHubSiteNavigation function exports the hub site navigation from the site provided to a CSV file. The CSV file is then used by the Copy-SPOHubSiteNavigation function to replicate the navigation links to other sites. The process could be hijacked somewhat to add hub site navigation from a CSV file rather than reading it from an existing hub site. We found it was easier to get a feel for the navigation in a real SharePoint site rather than work with the information in a spreadsheet.

Screen recording of the Copy-SPOHubSiteNavigation replicating navigation between two hub sites.
Screen recording of the Copy-SPOHubSiteNavigation replicating navigation between two hub sites.

You can also disable the export process by setting the -Export parameter to -Export:$false. This switch makes the Get-SPOHubSiteNavigation quite useful for displaying the hub site navigation in an accessible collection. This collection can be used with pipe functions, to filter or sort the collection, for example. This collection is also much easier to work with than using the Get-PnpNavigationNode -Location TopNavigatioBar -Tree cmdlet and parameters to show the full navigation structure.

Hub site navigation collection displayed in a table.
Hub site navigation collection displayed in a table.

Observations

As with many of my posts, I like to share any observations I have made during the work.

  • The cached Hub navigation appears to refresh every 30 minutes if left unchanged. You can force the cache to refresh by editing the links and then clicking cancel.
  • A JSON file gets saved to the /_catalogs/hubsite library which could be related to the cached navigation. It has a GUID based name e.g. 20d31c78-8a8c-499a-b953-ecc673344cef.json and appears to get modified by the System Account when changes to the hub site navigation are saved.
  • The cached JSON file looks like this:
  • This JSON file, in theory, could be read from a source site and the navigation element copied and injected into the JSON on a target site through manipulation of the JSON payload and the /_API/navigation/SaveMenuState API.
  • When trying to add a new navigation node using the Add-PnpNavigationNode cmdlet. If the parent node was invalid I got the following error. This wasn’t because the URL linked to a file or folder that didn’t exist as the error below suggests.
Add-PnPNavigationNode error
Add-PnPNavigationNode : error when no resource or file is available from the Url supplied.
  • The script could benefit additional error handling, particularly to ensure the target site(s) provided are registered as hub sites.
  • Bonus tip! If you find you have lost changes to the navigation, this same JSON file is part of a library where version history is enabled. This file appears in hub sites and sites associated with a hub site. The version history might help you recover from any loss, but you won’t be able to restore it as the library appears to be read-only.
Version history available for JSON file which I suspect ins the cached hub site navigation
Version history available for JSON file which I suspect ins the cached hub site navigation

I hope you find this post useful. As always #SharingIsCaring

Working with SharePoint’s Second Stage Recycle Bin in PowerShell

I thought I’d share a PowerShell script that I’ve created to perform a few tasks against a Site Collection Second Stage Recycle Bin (SSRB) in SharePoint.

Remove-SecondStageRecycleBinItems.ps1
Remove-SecondStageRecycleBinItems.ps1

The requirement was to delete items that were older than a set number of days from the Second Stage Recycle Bin (SSRB). A record of each item deleted also needed to be added to a report.  But SharePoint can do this already I hear you say…well yes if a Site Collection quotas and the auditing features are used. In this scenario neither could be.

To display items in the Second State Recycle Bin in a table I used this command.

$site.Recyclebin | where { $_.ItemState -eq "SecondStageRecycleBin" -and $_.deleteddate -le $dateDiff} | Format-Table -Property Title, Web, DeletedBy, DeletedDate -Autosize -Wrap

Then to remove each item from the Recycle Bin I used the delete command.

$site.Recyclebin.Delete($_.ID)

The full script is shared below. Remember to review, rename and test this script before using it in a production environment.

One quirk I found while creating the script was that through the web browser, SharePoint reported the time each file was deleted correctly whereas, in PowerShell, the time was not honouring GMT summer time.

British Summer Time  in SharePoint vs. PowerShell
British Summer Time in SharePoint vs. PowerShell

Enjoy and delete carefully!

All #SPC14 sessions available in a single spreadsheet!

Update: Wednesday, 8th January 2014. This post has seen an incredible amount of traffic which I have found to be a very rewarding experience- thank you! I’ve lived up to my word and managed to export the speaker information. Both the spreadsheet and PowerShell script has been updated to include this information.

Something I have found frustrating with the SharePoint Conference 2014 website over the holidays is that you have to browse through the sessions as search results pages. It makes planning how I want to fill my days at the conference very difficult.

Spreadsheet containing all the SharePoint Conference 2013 sessions
Spreadsheet containing all the SharePoint Conference 2014 sessions

I also wanted to sit down with my colleagues to see if there are any particular sessions that interest them. Without all the sessions available in a format such as a spreadsheet this would become a very tiresome task.

There was no way I was going to do this by hand – at this time there is about 183 published sessions and 12 pieces of information per session that would require me to use copy and paste 4392 times and click between a browser and Excel 600 times…no thank you

Jumping the gun the a little maybe as I have yet to register (this is top of my to-do list when I’m back in the office on Monday and I’ll kick myself if this is available when you register!) but I broke out PowerShell and wrote a script to download all the information for the sessions from the SharePoint Conference (#SPC14) website to a spreadsheet – both of which you can download.

PowerShell script to export all the #SPC14 sessions to Excel
PowerShell script to export all the #SPC14 sessions to Excel

A spreadsheet of all the SPC14 sessions can be downloaded with this link and the script is available here.

By no means is this script particularly complex or elegant – but I really wanted this information in a spreadsheet and pretty fast so forgive me if it is not up to my usual standard…the key thing is I achieved what I set out to do and can share it with you all. The last piece of information which I’m still trying to export are the speakers for the sessions – I’ll update if I manage it.

I hope you find the #SPC14 session spreadsheet helpful – see you at the conference!

Security trimmed top navigation links

I was asked to review a client environment yesterday to find out why the links in their top navigation bar were displaying for users that did not have permission to the particular sites.

Creating sites

It turns out that when sites were being created by the client on SharePoint Foundation 2010 they were being created without the ‘include on the top navigation bar’ check box ticked. As a result, the link was then not automatically added to the top navigation bar but instead later manually added and so was not security trimmed link.

Display this site on the top link bar of the parent site
Display this site on the top link bar of the parent site

It was then after removing permissions to the various sites that it became clear that users were able to see the top navigation bar link to the sites even though they did not have access.

Obviously, there are situations when users don’t have permissions to a site and you don’t want them to see that the site even exists. An example of this might be in an extranet scenario when you have third parties accessing project sites and you don’t want those third parties seeing the names of other project sites that may exist let alone the content…so how do we prevent this?

Identifying security trimmed links

By reviewing the URLs of the links in the top navigation bar I was able to identify whether the links were security trimmed or not. If the field for the URL is disabled then the link is security trimmed and most probably created when as the site was created.

Custom top navigation link that is not security trimmed
Custom top navigation link that is not security trimmed
Security trimmed top navigation link
Security trimmed top navigation link

Adding new security trimmed links

After identifying the problem, I then had to make the existing links security trimmed. I did this in two stages. The first was to make a note of the position of the link that needed to be replaced. I then deleted it from the top navigation bar using the ‘Top Link Bar’ site settings page (_layouts/topnav.aspx). The second stage was then to create the new security trimmed link by using the PowerShell code below.

Modify the $SPWeb and @(“Site Name”, “/sitename/default.aspx”) arguments as required and run the code for each of the top navigation bar links that need to be security trimmed. Remember the old link will need to be removed and the new one ordered as required.

Conclusion

It appears SharePoint, specifically SharePoint Foundation 2010 only honours security trimmed links in the top navigation when the links are created automatically as opposed to being created manually.

Note: this post specifically targets SharePoint 2010 Foundation which does not include the extended navigation that is included as part of the Publishing feature.