Learning and Sharing
  • Home
  • Blog
  • Linux
  • macOS
  • Virtualization
    • VMware
    • VirtualBox
  • Windows
    • Windows 11
    • Windows 10
    • Windows Server
  • Series
    • Symantec
    • Intune
    • Microsoft Azure
    • Powershell
    • VirtualBox
    • VMware
    • PowerShell Learning
    • Microsoft Graph
  • More
    • Auto Installation
    • AEC Installation
  • Contact
No Result
View All Result
  • Home
  • Blog
  • Linux
  • macOS
  • Virtualization
    • VMware
    • VirtualBox
  • Windows
    • Windows 11
    • Windows 10
    • Windows Server
  • Series
    • Symantec
    • Intune
    • Microsoft Azure
    • Powershell
    • VirtualBox
    • VMware
    • PowerShell Learning
    • Microsoft Graph
  • More
    • Auto Installation
    • AEC Installation
  • Contact
No Result
View All Result
No Result
View All Result

How to Use Splatting with Invoke-RestMethod in Graph PowerShell

October 6, 2023
in Blog, Microsoft Graph, Powershell
0
ADVERTISEMENT

Table of Contents

We already know that when we make a call to Microsoft Graph, we need to be able to make an API call that includes the endpoint, method, and any information needed to complete our request.

The next step is to take that information and be able to use it in a PowerShell script. This post will cover some important tips and tricks to get the most out of Microsoft Graph when working with PowerShell.

There are a lot of different things we could cover, but as we have been working through this blog post, we wanted to break it down to three main areas: 

  • Using the right version of PowerShell
  • Splatting
  • And a primer understanding return codes.

Using the right version of PowerShell

The Graph PowerShell SDK is powerful but doesn’t support custom API calls. Invoke-RestMethod is a much more flexible option. We can make any REST API call we want to, it is native to PowerShell, and it automatically converts JSON or XML responses to PowerShell objects.

We want to help you build custom tools that will work in any environment, and that makes Invoke-RestMethod the best option.

Invoke-RestMethod is part of the PowerShell.Utility module. If you’re following this post, you probably already imported the MSAL module, so we don’t need to import anything else to access Microsoft Graph

PS C:\> Get-InstalledModule MSAL.PS

Version              Name                                Repository
-------              ----                                ----------
4.37.0.0             MSAL.PS                             PSGallery 

Invoke-RestMethod was updated in PowerShell version 7. The StatusCodeVariable parameter was added. This parameter allows us to easily pass the return code from our REST call back to our script.

It’s not a requirement, but it will make troubleshooting and more robust scripts possible. If you aren’t already using PowerShell version 7, we highly recommend installing PowerShell 7 now.

Invoke-RestMethod is used to send requests to Microsoft Graph (or any other REST API). There are several different parameters available, but there are only a handful we will need to use regularly. We commonly use Method, Uri, Headers, Body, and StatusCodeVariable.

  • Method – this is the verb that describes what we are trying to do with our API call.
  • Uri – this is the endpoint (or URL) we are accessing.
  • Headers – the Header include information requiring in the request, including our authorization token and accepted response type.
  • Body – this is a JSON payload that is delivered as part of a PUT, PATCH, or POST call.
  • StatusCodeVariable – the status code variable tells PowerShell where to store the status code returned by the service

We can pass each one of these parameters to Invoke-RestMethod in a single line of code. That’s fine for calling Invoke-RestMethod from a terminal, but it’s going to be difficult to read in a script. It also means that we may have to make multiple API calls with explicitly defined parameters. This is cumbersome and doesn’t follow best practices for scripting.

Splatting

Splatting in PowerShell is used to pass parameters into a command using either a hashtable or an array. Arrays can be used to pass positional parameters, while hashtables can be used to pass named parameters.

Splatting allows you to reuse code, which will help to keep your scripts cleaner and easier to read. If you reuse splats with common parameters, you will be able to consistently pass common parameters and minimize errors. Parameters can be updated or added to a splat at any time prior to making an API call.

A simple splat for a GET request could look like this:

$graphParams = @{
    Headers  = @{
        "Content-Type"  = "application/json"
        "Authorization" = "Bearer $token"
    }
    Method   = "GET"
    URI      = "https://graph.microsoft.com/v1.0/users"
    StatusCodeVariable = "SCV"
    ErrorAction = "SilentlyContinue"
}

When we create a splat, we are creating a hashtable using the $variable = @{ key = “value” } format. Each parameter we want to add to the splat is used as a key in our hashtable, and the values are set accordingly. We can call Microsoft Graph using the following format:

$result = Invoke-RestMethod @graphParams

The result is returned as a PSCustomObject.

PS C:\> $result | Get-Member

   TypeName: System.Management.Automation.PSCustomObject

Name            MemberType   Definition
----            ----------   ----------
Equals          Method       bool Equals(System.Object obj)
GetHashCode     Method       int GetHashCode()
GetType         Method       type GetType()
ToString        Method       string ToString()
@odata.context  NoteProperty string @odata.context=https://graph.microsoft.com/v1.0/$metadata#users
@odata.nextLink NoteProperty string @odata.nextLink=https://graph.microsoft.com/v1.0/users?$skiptoken=RFNwdAIAAQAAABI6VXNlcjEwMjVAbXNlZHUudm4pVXNlcl8yMm…
value           NoteProperty Object[] value=System.Object[]

We can view the results returned from the API call by calling the $_.value property of the object. Since it is a PowerShell object, we can even pipe the value to another command. In this case, we wanted to view all the users returned that had a DisplayName that starts with “Allan“.

$result.value | Where-Object DisplayName -like 'Allan*'
businessPhones    : {}
displayName       : Allan Deyoung
givenName         :
jobTitle          :
mail              : [email protected]
mobilePhone       :
officeLocation    :
preferredLanguage :
surname           :
userPrincipalName : [email protected]
id                : 19d877b4-b2f8-456d-ad26-766dec8f5d74

We also added the StatusCodeVariable parameter to our splat. By calling the variable we set, in this case $SCV, we can view the status code that was returned.

PS C:\> $scv
200

Add parameters or update existing parameters in a splat

We can add additional parameters or update existing parameters in a splat by using the format $SplatVariable[“Key”] = “New Value”. We can see that in the following example:

We will start by creating a hashtable without the URI key.

$graphParams = @{
    Headers  = @{
        "Content-Type"  = "application/json"
        "Authorization" = "Bearer $token"
    }
    Method   = "GET"
    StatusCodeVariable = "SCV"
    ErrorAction = "SilentlyContinue"
} 

The hashtable was created without the Uri key:

PS C:\> $graphParams

Name                           Value
----                           -----
Method                         GET
Headers                        {[Content-Type, application/json], ...
ErrorAction                    SilentlyContinue
StatusCodeVariable             SCV

We can add a URI to the hashtable with the following command:

$graphParams["URI"]= "https://graph.microsoft.com/beta/users"

When we return the variable, we can see the URI has been added to our hashtable.

PS C:\> $graphParams

Name                           Value
----                           -----
Method                         GET
URI                            https://graph.microsoft.com/beta/users
Headers                        {[Content-Type, application/json], ...
ErrorAction                    SilentlyContinue
StatusCodeVariable             SCV

We can update a value using the exact same command:

$graphParams["URI"]= "https://graph.microsoft.com/v1.0/devices"
PS C:\> $graphParams

Name                           Value
----                           -----
URI                            https://graph.microsoft.com/v1.0/devices
Method                         GET
Headers                        {[Content-Type, application/json], ...
StatusCodeVariable             SCV
ErrorAction                    SilentlyContinue

Splatting in PowerShell script

There are different ways we can approach using splatting in PowerShell scripts. One approach is to create a splat for each type of API call we will make at the start of our script, and then call the specific splat when we need to call Invoke-RestMethod.

If we take this approach, we will need to have multiple splats declared early in our script. We will also need to add or update the URI and Body each time we use a splat. For example, if we have a script that will be making GET, POST, and PATCH calls, we could include the following section in our script:

#Create MS Graph Splats
#Create GET splat
$graphParams = @{
    Headers     = @{
        "Content-Type"  = "application/json"
        "Authorization" = "Bearer $token"
    }
    Method      = "GET"
    ErrorAction = "SilentlyContinue"
    StatusCodeVariable = "SCV"
}

#Create POST splat
$graphPostParams = @{
    Headers     = @{
        "Authorization" = "Bearer $token"
        "Accept"        = "application/json"
        "Content-Type"  = "application/json"
    }
    Method      = "POST"
    ErrorAction = "SilentlyContinue"
    StatusCodeVariable = "SCV"
}

#Create PATCH splat
$graphPatchParams = @{
    Headers     = @{
        "Authorization" = "Bearer $token"
        "Content-Type"  = "application/json"
    }
    Method      = "PATCH"
    ErrorAction = "SilentlyContinue"
    StatusCodeVariable = "SCV"
}

If we take this approach, we can add the additional parameters to the splat immediately before running Invoke-RestMethod. For example, if we want to return all Entra ID Users, we can use the following script to connect to Microsoft Graph, create a splat hashtable, and finally call Invoke-RestMethod:

#Use a client secret to authenticate to Microsoft Graph
$authparams = @{
    ClientId    = "xxxxxxxxxxxxxxxxxxxxxxx"
    TenantId    = "xxxxxxxxxxxxxxxxxxxxxxx"
    ClientSecret = ('xxxxxxxxxxxxxxxxxxxxxxx' | ConvertTo-SecureString -AsPlainText -Force )
}
$auth = Get-MsalToken @authParams
$AccessToken = $Auth.AccessToken

#Create MS Graph Splats
#Create GET splat
$graphParams = @{
    Headers     = @{
        "Content-Type"  = "application/json"
        "Authorization" = "Bearer $AccessToken"
    }
    Method      = "GET"
    ErrorAction = "SilentlyContinue"
    StatusCodeVariable = "SCV"
}

$graphParams["URI"]= “https://graph.microsoft.com/beta/users”
$Result = Invoke-RestMethod @graphParams
$Result

This will return our users to a PSCustomObject as we demonstrated in the first example.

PS C:\> $Result

@odata.context                                   value
--------------                                   -----
https://graph.microsoft.com/beta/$metadata#users {@{id=cd90a87a-7156-4f6a-88b5-5ee908354b3c; deletedDateTime=; accountEnabled=True; ageGroup=; businessP…

Perhaps the better option would be to include a splat as part of a function. PowerShell functions allow us to reuse code, so we could simply create a different function for each method, but we can take it a step further.

By passing in parameters for the URI, method, and body, we can use a single function to handle every method available to us in Microsoft Graph.

[cmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        [string]$token,
        [Parameter(Mandatory=$True)]
        [string]$URI,
        [Parameter(Mandatory=$True)]
        [string]$Method,
        [Parameter(Mandatory=$False)]
        [string]$Body
    )

We can adjust the Splat in the function to account for different methods. In this case, both the method and URI values are variables. Their values are being passed in from the function’s parameters.

#Create Splat hashtable
    $graphParams = @{
        Headers     = @{
            "Content-Type"  = "application/json"
            "Authorization" = "Bearer $token"
        }
        Method = $Method
        URI = $URI
        ErrorAction = "SilentlyContinue"
        StatusCodeVariable = "scv"
    }

Some methods require a body, but not all of them do. We want to be able to add the body to our splat, but only if it is needed. We can accomplish that with a conditional statement that looks for methods that require a body.

#If method requires body, add body to splat
    If($Method -in ('PUT','PATCH','POST')){
        $graphParams["Body"] = $Body
    }

Finally, we will make our API call using Invoke-RestMethod. Any value returned will be returned to the $MSGraphResult variable. That value and our status code variable will be returned to the main script.

#Return API call result to script
$MSGraphResult = Invoke-RestMethod @graphParams

#Return status code variable to script
Return $SCV, $MSGraphResul

Create a function with spatting

Now that we have created our function. We know that we can update the job title of a user with a PATCH request to https://graph.microsoft.com/v1.0/users/{userid}

We need to include the job title in the body of the request, so we will have to pass the body to the function through a parameter. In our example, in the below screenshot, the job title is empty for this user.

LROV9AdrE8jmMrucjkr8FG3bWcWPCGJJHW2sFcFlZaJBEoCIZxNy8veBpUFA

We have created a script that includes the function outlined above. This script authenticates to MS Graph using an app registration and a client secret. Each value we need to pass into our function is saved to a variable, and each variable is being passed to the function.

Note Note: The BODY parameter needs to be passed to Invoke-RestMethod as JSON. When we create the $Body variable, we create a hashtable and pipe that to ConvertTo-JSON as shown in the script below.
#Function to make Microsoft Graph API calls
Function Invoke-MsGraphCall {
    [cmdletBinding()]
    param(
        [Parameter(Mandatory=$True)]
        [string]$Token,
        [Parameter(Mandatory=$True)]
        [string]$URI,
        [Parameter(Mandatory=$True)]
        [string]$Method,
        [Parameter(Mandatory=$False)]
        [string]$Body
    )
    #Create Splat hashtable
    $graphParams = @{
        Headers     = @{
            "Content-Type"  = "application/json"
            "Authorization" = "Bearer $Token"
        }
        Method = $Method
        URI = $URI
        ErrorAction = "SilentlyContinue"
        StatusCodeVariable = "scv"
    }

    #If method requires body, add body to splat
    If($Method -in ('PUT','PATCH','POST')){
        $graphParams["Body"] = $Body
    }

    #Return API call result to script
    $MSGraphResult = Invoke-RestMethod @graphParams

    #Return status code variable to script
    Return $SCV, $MSGraphResult

}

#Create required variables
$URI = "https://graph.microsoft.com/v1.0/users/cd90a87a-7156-4f6a-88b5-5ee908354b3c"
$Body = @{ "jobTitle" = "Sales Manager" } | ConvertTo-Json
$Method = "PATCH"

#Call Invoke-MsGraphCall
$MSGraphCall = Invoke-MsGraphCall -AccessToken $Token -URI $URI -Method $Method -Body $Body

$LastStatusCode = $MSGraphCall[0]
$ReturnedValue = $MSGraphCall[1].value

$ReturnedValue
Write-Host "SCV is $LastStatusCode"

The PATCH method doesn’t return a value, so there is no value for $ReturnedValue, but a status code value was returned. We can see that in our terminal after running the script. 204 is the exit code that we would expect for a successful PATCH request.

PS E:\> E:\scripts\graph_splat_function.ps1
SCV is 204

We can also see that the job title of the user was updated as we expected:

8VDgOvBSbaVjihv7wGZykpUuoe1Ma8F3EArdb1JMr2J9N03hYmZlwD8ppYUd

Microsoft Graph Response Codes

When we make calls to Microsoft Graph, we always expect a response code, whether the API call was successful or not. These response codes are essential for understanding whether our call was accepted and processed successfully. If the API call failed, the response code can be essential to understand what went wrong and how to correct it. The following table lists some of the most common error codes you may encounter.

You can find out more information about status codes here.

5/5 - (1 vote)
Previous Post

What is the Microsoft Graph API?

Next Post

How to Copy Files without Changing Date Creation Time on Windows

Related Posts

Running Hyper-V and VMware Workstation on The Same Machine

August 15, 2024

How to Uninstall All Autodesk Products At Once Silently

July 29, 2024
Ftr5

How to Uninstall the Autodesk Genuine Service on Windows

July 29, 2024
Ftr19

How to Fix Windows Cannot Read the ProductKey From the Unattend Answer File in VirtualBox

July 26, 2024
Ftr25

How to Update Windows Terminal in Windows 10/11

July 26, 2024

How to Disable The Beep Sound in WSL Terminal on Windows

July 26, 2024

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • How To Turn On uBlock Origin Extension in Chrome (2025)
  • Images Hidden Due To Mature Content Settings In CivitAI
  • Azure OpenAI vs Azure AI Hub, How to Choose the Right One for Your Needs

Categories

Stay in Touch

Discord Server

Join the Discord server with the site members for all questions and discussions.

Telegram Community

Jump in Telegram server. Ask questions and discuss everything with the site members.

Youtube Channel

Watch more videos, learning and sharing with Leo ❤❤❤. Sharing to be better.

Newsletter

Join the movement and receive our weekly Tech related newsletter. It’s Free.

General

Microsoft Windows

Microsoft Office

VMware

VirtualBox

Technology

PowerShell

Microsoft 365

Microsoft Teams

Email Servers

Copyright 2025 © All rights Reserved. Design by Leo with ❤

No Result
View All Result
  • Home
  • Linux
  • Intune
  • macOS
  • VMware
  • VirtualBox
  • Powershell
  • Windows 10
  • Windows 11
  • Microsoft 365
  • Microsoft Azure
  • Microsoft Office
  • Active Directory

No Result
View All Result
  • Home
  • Linux
  • Intune
  • macOS
  • VMware
  • VirtualBox
  • Powershell
  • Windows 10
  • Windows 11
  • Microsoft 365
  • Microsoft Azure
  • Microsoft Office
  • Active Directory