powershellazure-rest-apiinvoke-webrequestinvoke-restmethod

Different results from Invoke-WebRequest and Invoke-RestMethod


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"}

Solution

  • The problem:

    In short:


    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=}