Different results from Invoke-WebRequest and Invoke-RestMethod
Asked Answered
G

1

8

I am trying to call Azure Rest API and get Schedules of DevTestLabs. I tried Invoke-RestMethod, but it doesn't give value on "dailyRecurrence" key. But Invoke-WebRequest does.

What would be the reason for that?

URL

$url = "https://management.azure.com/subscriptions/{subscriptionID}/resourceGroups/{resourseGroup}/providers/Microsoft.DevTestLab/labs/{LabName}/schedules/LabVmsShutdown?api-version=2018-10-15-preview"

URL with $expand

$url = "https://management.azure.com/subscriptions/{subscriptionID}/resourceGroups/{resourseGroup}/providers/Microsoft.DevTestLab/labs/{LabName}/schedules/LabVmsShutdown?$expand=properties(dailyRecurrence)&api-version=2018-10-15-preview"

Calling Invoke-RestMethod

$output = Invoke-RestMethod -Uri $url -Method "GET" -ContentType "application/json" -Headers $authHeaders

properties : @{status=Enabled; taskType=LabVmsShutdownTask; dailyRecurrence=; timeZoneId=AUS Eastern Standard Time;
         notificationSettings=; createdDate=26/03/2019 4:38:18 PM; provisioningState=Succeeded;
         uniqueIdentifier=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}

Calling Invoke-WebRequest

$output = Invoke-WebRequest -Uri $url -Method "GET" -Headers $authHeaders

Content           : {"properties":{"status":"Enabled","taskType":"LabVmsShutdownTask","dailyRecurrence":{"time":"1900"}
                ,"timeZoneId":"AUS Eastern Standard Time","notificationSettings":{"status":"Disabled","timeInMinute
                s":30},"createdDate":"2019-03-26T03:38:18.0726376+00:00","provisioningState":"Succeeded","uniqueIde
                ntifier":"XXXXXXXXXXXXXXXXXXXXXXXXX"},"id":"/subscriptions/XXXXXXXXXXXXXXXXXXX/resourcegroups/XXXXXXXXXXXXX/providers/microsoft.devtestlab/labs/XXXXXXXX/schedules/labvmsshutdown","name":"LabVmsShutdown","type":"microsoft.devtestlab/labs/schedules","location":"australiasoutheast"}
Gobelin answered 26/10, 2021 at 23:52 Comment(0)
T
13

The problem:

  • is merely a display problem,

  • albeit one that exposes a long-standing bug, still present as of PowerShell Core 7.3.3, namely that [pscustomobject] instances mistakenly stringify to the empty string - see GitHub issue #6163.

In short:

  • The data is there in the Invoke-RestMethod output, it just appears to be missing - see the next section.
  • Use $output.properties.dailyRecurrence to see it or, to more helpfully visualize the output, use it $output | ConvertTo-Json to re-convert it to (prettified) JSON.
    • Note: Situationally, you may have to add a -Depth argument to fully represent object graphs with a depth greater than 2 - see this post.

Invoke-RestMethod - unlike Invoke-WebRequest - has deserialization built in: with a JSON response, it automatically parses the JSON text returned into a [pscustomobject] graph as if ConvertFrom-Json had been applied to it.

You're seeing the default formatting of the resulting object graph, which isn't really suited to visualizing nested [pscustomobject] instances, which are represented by their .ToString() values - and therefore - due to the bug - may appear to have no value, even when they do.

By contrast, since the output from Invoke-WebRequest reports the JSON text as-is in the .Content property of its output objects, the problem doesn't surface there.

A simple demonstration of the bug:

[pscustomobject] @{ 
  nested = 
    [pscustomobject] @{ 
      deep = 
        [pscustomobject] @{ 
          deepest = 'down'
        } 
    } 
}

As of PowerShell Core 7.3.3, this yields the following, mistakenly suggesting that .nested.deep has no value, even though it clearly does:

nested
------
@{deep=}
Tartu answered 27/10, 2021 at 1:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.