Search code examples
powershellsharepointsharepoint-2010odatapowershell-3.0

Access SharePoint expanded properties


I'm accessing a SharePoint lists has an associated stakeholder entity--I'm having difficultly accessing the stakeholder's properties.

The 'primary' content's properties are located on xpath /feed/entry/content/properties/*. The stakeholder's properties are located on xpath /feed/entry/link/inline/entry/content/properties/*.

Assuming that I include the stakeholder's name in the odata query:

http://server/list/_vti_bin/listdata.svc/TheList?$select=Id,Title,Stakeholder/Name&$expand=Stakeholder

How do I reference the stakeholder's properties when enumeration the feed's properties?

Using this code, the Stakeholder.Name property is not populated:

(Invoke-RestMethod -Uri $url -Method Get -UseDefaultCredentials).entry.content.properties | Foreach {
  [PsCustomObject]@{
    Id=$_.Id."#text"; 
    Title=$_.Title; 
    StakholderName=$_.Stakeholder.Name;
  }
}

Do I need to populate a second PsCustomObject for the stakeholder, then merge the 'primary' data?


Solution

  • The query is malformed since $ symbol have to be escaped using single-quoted string literals, for example:

    $url = "http://contoso.intranet.com/_vti_bin/listdata.svc/TheList?`$select=Id,Title,Stakeholder/Name&`$expand=Stakeholder"
    

    Then Stakeholder value could retrieved as demonstrated below:

    $StakeholderValue = $data.link | where { $_.title -eq "Stakeholder" } | select -Property @{name="Name";expression={$($_.inline.entry.content.properties.Name)}}
    

    Modified example

    $url = "http://contoso.intranet.com/_vti_bin/listdata.svc/TheList?`$select=Id,Title,Stakeholder/Name&`$expand=Stakeholder"
    
    $data = Invoke-RestMethod -Uri $url -Method Get -UseDefaultCredentials -ContentType "application/json;odata=verbose"  
    
    $data  | Foreach {
        [PsCustomObject]@{
           Id = $_.content.properties.Id."#text"; 
           Title = $_.content.properties.Title; 
           Stakeholder = $_.link | where { $_.title -eq "Stakeholder" } | select -Property @{name="Name";expression={$($_.inline.entry.content.properties.Name)}}
        }
    }
    

    Alternatively i would propose to consider another approach. By default SharePoint 2010 REST service returns results in xml format. The idea is to return results in json format instead.

    Unfortunately neither Invoke-RestMethod nor Invoke-WebRequest could not be utilized for that purpose since both of them contain a bug in PowerShell 3.0 according to Microsoft Connect.

    This particular bug prevents us to consume SharePoint REST services since since Accept header could not be specified and therefore results could not be returned in json format

    Having said that, i would recommend to leverage WebClient Class.

    Below is demonstrated the same example that returns results in JSON format. Note that getting of List Item properties become a way easier compared to the original example :

    Function Execute-RequestJson()
    {
    Param(
      [Parameter(Mandatory=$True)]
      [string]$Url,
      [Parameter(Mandatory=$False)]
      [System.Net.ICredentials]$Credentials,
      [Parameter(Mandatory=$False)]
      [bool]$UseDefaultCredentials = $True,
      [Parameter(Mandatory=$False)]
      [Microsoft.PowerShell.Commands.WebRequestMethod]$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get 
    )
    
       $client = New-Object System.Net.WebClient
       if($Credentials) {
         $client.Credentials = $Credentials
       }
       elseif($UseDefaultCredentials){
         $client.Credentials = [System.Net.CredentialCache]::DefaultCredentials 
       }
       $client.Headers.Add("Content-Type", "application/json;odata=verbose")
       $client.Headers.Add("Accept", "application/json;odata=verbose")
       $data = $client.DownloadString($Url)
       $client.Dispose()
       return $data | ConvertFrom-Json
    }
    
    
    
    
    
    $url = "http://contoso.intranet.dev/_vti_bin/listdata.svc/TheList?`$select=Id,Title,Stakeholder/Name&`$expand=Stakeholder"
    $data = Execute-RequestJson -Url $url -UseDefaultCredentials $true
    
    $data.d.results | Foreach {
        [PsCustomObject]@{
           Id = $_.Id; 
           Title = $_.Title; 
           Stakeholder = $_.Stakeholder.Name
        }
    }