Spring til indholdet

Navigationen på et SharePoint-websted med REST

Hent, opret, ret og slet links i Quick Launch og den øverste navigation med REST fra Power Automate og med PnP PowerShell.

Opdateret Power AutomatePowerShellSharePoint Online 5 min. læsning

Når et nyt websted skal have samme navigation som de andre, eller et link skal rettes på tyve websteder, går det hurtigere med REST end i browseren. Navigationen er to samlinger af noder på webben:

GET _api/web/navigation/quicklaunch
GET _api/web/navigation/topnavigationbar

På et almindeligt teamwebsted er det Quick Launch, der er webstedets navigation — også når den er sat til at stå vandret øverst på siden. På et kommunikationswebsted er det topnavigationbar. Hubnavigationen over et websted, der er tilknyttet en hub, hører til hubwebstedet og rettes der. Det sidste har jeg ikke efterprøvet via REST.

Handlingen Send an HTTP request to SharePoint hører til SharePoint-connectoren og kræver ikke Premium.

En node#

1{
2  "Id": 1001,
3  "Title": "Departments",
4  "Url": "https://site.sharepoint.com/departments",
5  "IsExternal": false,
6  "IsVisible": true,
7  "AudienceIds": []
8}

Url må være relativ eller fuld. IsExternal er true for et link uden for webstedssamlingen. AudienceIds begrænser, hvem der ser noden. Tom betyder alle, og det virker kun, når målretning mod målgrupper er slået til for navigationen.

Hent#

GET _api/web/navigation/topnavigationbar/getbyid(1001)
GET _api/web/navigation/quicklaunch/getbyid(1001)/children

Samlingen giver kun det øverste niveau. Undernoderne kommer med /children på den enkelte node.

En node ud fra navnet. Id’et står ingen steder i brugerfladen, så i et flow finder jeg det ud fra titlen. Metoden er fra Expiscornovus’ “Get navigation node by name”. Først alle noderne:

Site Address: [Your SharePoint site]
Method: GET
Uri: _api/web/navigation/quicklaunch
Headers:
{
  "Accept": "application/json;odata=verbose"
}

Så Parse JSON med dette skema:

 1{
 2  "type": "object",
 3  "properties": {
 4    "d": {
 5      "type": "object",
 6      "properties": {
 7        "results": {
 8          "type": "array",
 9          "items": {
10            "type": "object",
11            "properties": {
12              "Id": { "type": "integer" },
13              "Title": { "type": "string" },
14              "Url": { "type": "string" }
15            }
16          }
17        }
18      }
19    }
20  }
21}

Filter array på titlen og en Compose med id’et:

From: body('Parse_JSON')?['d']?['results']
Where: item()?['Title'] equals 'Departments'
Inputs: first(body('Filter_array'))?['Id']

Titlen er den, brugerne ser, og på et dansk websted er den dansk.

Opret#

POST _api/web/navigation/topnavigationbar
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose"
}
Body:
{
  "__metadata": { "type": "SP.NavigationNode" },
  "Title": "Resources",
  "Url": "/sites/resources",
  "IsVisible": true
}

Samme body til quicklaunch, og til getbyid(1001)/children for en undernode.

En standardnavigation til et nyt websted er et array og en løkke:

Name: varTopNavItems
Type: Array
Value:
[
  { "Title": "Home", "Url": "/" },
  { "Title": "Departments", "Url": "/sites/departments" },
  { "Title": "Resources", "Url": "/sites/resources" },
  { "Title": "Help", "Url": "/sites/help" }
]
Method: POST
Uri: _api/web/navigation/topnavigationbar
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose"
}
Body:
{
  "__metadata": { "type": "SP.NavigationNode" },
  "Title": "@{items('Apply_to_each')?['Title']}",
  "Url": "@{items('Apply_to_each')?['Url']}",
  "IsVisible": true
}

En ny node lægges sidst. Løkken skal derfor køre én ad gangen (Concurrency control slået fra), ellers er rækkefølgen tilfældig.

Ret#

POST _api/web/navigation/topnavigationbar/getbyid(1001)
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose",
  "X-HTTP-Method": "MERGE",
  "IF-MATCH": "*"
}
Body:
{
  "__metadata": { "type": "SP.NavigationNode" },
  "Title": "Updated Title",
  "Url": "/new-url"
}

Slet#

POST _api/web/navigation/quicklaunch/getbyid(1001)
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose",
  "X-HTTP-Method": "DELETE",
  "IF-MATCH": "*"
}

Hele Quick Launch ryddes med en GET, en Apply to each over body('Parse_JSON')?['d']?['results'] og et DELETE pr. node:

Method: POST
Uri: _api/web/navigation/quicklaunch/getbyid(@{items('Apply_to_each')?['Id']})
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose",
  "X-HTTP-Method": "DELETE",
  "IF-MATCH": "*"
}

Om en overordnet node kan slettes, mens den har undernoder, har jeg ikke efterprøvet. Slettes undernoderne først, er spørgsmålet væk.

Arvet navigation#

Et underwebsted kan arve den øverste navigation fra sit overordnede websted, og så er der ingen egne noder at rette. Det styres af UseShared på SP.Navigation, som godt kan sættes. Via REST er det formentlig en MERGE mod selve navigationen:

POST _api/web/navigation
Headers:
{
  "Accept": "application/json;odata=verbose",
  "Content-Type": "application/json;odata=verbose",
  "X-HTTP-Method": "MERGE",
  "IF-MATCH": "*"
}
Body:
{
  "__metadata": { "type": "SP.Navigation" },
  "UseShared": false
}

Ikke efterprøvet. Egenskaben er dokumenteret som skrivbar i CSOM, men kaldet her har jeg ikke kørt.

PnP PowerShell#

PnP har egne cmdlets til navigationen, og de er nemmere end at bygge REST-kald:

1Connect-PnPOnline -Url "https://<tenant>.sharepoint.com/sites/<websted>" -Interactive -ClientId "<klient-id>"
2
3Get-PnPNavigationNode -Location QuickLaunch
4Get-PnPNavigationNode -Location TopNavigationBar -Tree
1Add-PnPNavigationNode -Location QuickLaunch -Title "New Section" -Url "/new-section"
2Add-PnPNavigationNode -Location QuickLaunch -Title "Sub Section" -Url "/subsection" -Parent 1001
3Add-PnPNavigationNode -Location QuickLaunch -Title "Home" -Url "/" -First
1Remove-PnPNavigationNode -Identity 1001 -Force
2Get-PnPNavigationNode -Location QuickLaunch | Remove-PnPNavigationNode -Force

-Interactive kræver sit eget -ClientId fra en app-registrering. Add-PnPNavigationNode har også -PreviousNode, som placerer noden efter en bestemt node, og -AudienceIds.

Skal det være rå REST fra PowerShell, er Invoke-PnPSPRestMethod vejen. Den beder som standard om odata=nometadata, så noderne står i .value og ikke i .d.results:

1$quickLaunch = Invoke-PnPSPRestMethod -Method Get -Url "_api/web/navigation/quicklaunch"
2$quickLaunch.value | Format-Table Id, Title, Url

Den har ingen -Headers, så et DELETE med X-HTTP-Method kan ikke laves med den. Brug Remove-PnPNavigationNode.

Det der driller#

  • Rækkefølgen. En node, der oprettes med REST, lægges sidst, og REST-kaldet her har ingen måde at placere den på. CSOM har PreviousNode og AsLastNode ved oprettelsen, og PnP har -First og -PreviousNode. Ellers: opret i den rigtige rækkefølge.
  • Titlen er på webstedets sprog. En standardnavigation til både danske og engelske websteder skal have titlerne i to udgaver. Sproget står i _api/web?$select=Language (1030 er dansk, 1033 engelsk).
  • Den forkerte samling. Et kald mod topnavigationbar på et teamwebsted går formentlig igennem uden fejl, men noden vises ikke, fordi teamwebstedet viser Quick Launch. Ikke efterprøvet, men det første at tjekke, når en ny node ikke dukker op.
  • Arvet navigation har ingen egne noder. Er listen tom på et underwebsted, arver det måske fra sit overordnede websted.

Alle noter