Utiliser PowerShell et Visual Studio Code avec l’API web Dataverse
Cet article développe l’article Démarrage rapide : API web avec PowerShell pour décrire les fonctionnalités avancées utilisant PowerShell et Visual Studio Code avec l’API web Dataverse pour :
- Créer des fonctions réutilisables
- Gérer les exceptions
- Gérer les limites de protection de service Dataverse
- Déboguer avec Fiddler
- Télécharger le document $metadata CSDL de l’API web Dataverse
Notes
Les instructions de cet article devraient fonctionner pour Windows, Linux et macOS, mais ces étapes n’ont été testées que sous Windows. Si des modifications sont nécessaires, faites-le nous savoir en utilisant la section Commentaires au bas de cet article.
Conditions préalables
Le contenu de cet article présente les mêmes conditions préalables que l’article Démarrage rapide : API web avec PowerShell .
Installer ou vérifier que les éléments suivants sont installés
Installez Visual Studio Code. Voir Télécharger Visual Studio Code
Installez l’extension PowerShell pour Visual Studio Code. Voir PowerShell pour Visual Studio Code
Installez PowerShell 7.4 ou version ultérieure. Voir Installer PowerShell sur Windows, Linux et macOS
Installez le module Az PowerShell version 11.1.0 ou supérieure. Voir Procédure d’installation d’Azure PowerShell
Pour mettre à jour une installation existante vers la plus récente, utilisez
Update-Module -Name Az -Force
Vérifier l’installation
Ouvrez Visual Studio Code.
Dans le menu Terminal, sélectionnez Nouveau terminal.
Dans le volet de navigation Visual Studio Code, sélectionnez l’icône pour l’extension PowerShell.
Copiez et collez le script suivant dans la fenêtre du terminal Visual Studio Code :
Write-Host 'PowerShell Version:'$PSVersionTable.PSVersion.ToString() Write-Host 'PowerShell Az version:'(Get-InstalledModule Az).Version
Appuyez sur Entrée. La sortie ressemblerait à l’exemple suivant :
PowerShell Version: 7.4.0 PowerShell Az version: 11.1.0
Si vous ne voyez pas de résultats comme celui-ci, installez ou mettez à jour les prérequis.
Ce dont vous avez besoin
- Compte d’utilisateur valide pour un environnement Dataverse
- URL vers l’environnement Dataverse auquel vous souhaitez vous connecter. Voir Afficher les ressources des développeurs pour savoir comment les trouver. Cela ressemble à ceci :
https://yourorg.crm.dynamics.com/
, oùyourorg.crm
est différent. - Présentation de base du langage de script PowerShell
Créer des fonctions réutilisables
Démarrage rapide : API web avec PowerShell a présenté comment authentifier et appeler la fonction WhoAmI avec Visual Studio Code. Cette approche peut suffire à tester ponctuellement une ou plusieurs opérations. Cependant, à mesure que vos scripts deviennent plus complexes, vous pourriez vous retrouver à taper le même code encore et encore.
Dans cette section, nous commençons à créer un ensemble de fonctions réutilisables dans des fichiers séparés auxquels nous pouvons accéder à l’aide du dot sourcing. Utilisez le dot sourcing pour charger un fichier contenant des scripts PowerShell pouvant contenir des fonctions et des variables qui font partie de la portée du script local.
Conseil
Vous pouvez trouver des définitions entièrement documentées de ces fonctions et bien plus encore dans notre référentiel d’exemples GitHub PowerApps sur PowerApps-Samples/dataverse/webapi/PS/
Créer une fonction Connect
Mettons le code auquel s’authentifier à Dataverse dans une fonction appelée Connect
à l’intérieur d’un fichier nommé Core.ps1
afin de pouvoir le réutiliser dans une seule ligne de code.
Créez un dossier. Dans cet exemple, nous créons un dossier dans
C:\scripts
.Créez un fichier texte dans le dossier des scripts nommé
Core.ps1
.Copiez et collez la fonction
Connect
suivante dans le fichierCore.ps1
.function Connect { param ( [Parameter(Mandatory)] [String] $uri ) ## Login interactively if not already logged in if ($null -eq (Get-AzTenant -ErrorAction SilentlyContinue)) { Connect-AzAccount | Out-Null } # Get an access token $token = (Get-AzAccessToken -ResourceUrl $uri).Token # Define common set of headers $global:baseHeaders = @{ 'Authorization' = 'Bearer ' + $token 'Accept' = 'application/json' 'OData-MaxVersion' = '4.0' 'OData-Version' = '4.0' } # Set baseURI $global:baseURI = $uri + 'api/data/v9.2/' }
Notes
Le script ajoute les variables
baseURI
etbaseHeaders
au contexte global à l’aide du$global
modificateur de portée afin qu’elles soient disponibles pour d’autres scripts dans la même session.Créez un autre fichier texte dans Visual Studio Code nommé
test.ps1
dans votrescripts
dossier.Copiez et collez le script suivant dans le fichier
test.ps1
:. $PSScriptRoot\Core.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change to your organization # Invoke WhoAmI Function Invoke-RestMethod -Uri ($baseURI + 'WhoAmI') -Method Get -Headers $baseHeaders | ConvertTo-Json
. $PSScriptRoot\Core.ps1
en haut du fichier, dot sourcing utilise pour diriger le script afin de charger le contenu de ce fichier.N’oubliez pas de modifier
https://yourorg.crm.dynamics.com/
pour qu’il corresponde à l’URL de votre environnement.Pour exécuter le script, appuyez sur F5.
Le résultat pourrait ressembler à ce résultat :
PS C:\scripts> . 'C:\scripts\test.ps1' { "@odata.context": "https://yourorg.crm.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.WhoAmIResponse", "BusinessUnitId": "3a277578-5996-ee11-be36-002248227994", "UserId": "2c2e7578-5996-ee11-be36-002248227994", "OrganizationId": "97bf0e8b-aa99-ee11-be32-000d3a106c3a" }
Créer une fonction WhoAmI
Mettons le code pour appeler la fonction WhoAmI dans une fonction appelée Get-WhoAmI
à l’intérieur d’un fichier nommé CommonFunctions.ps1
afin que nous puissions taper simplement 11 caractères au lieu de 100 à chaque fois que vous souhaitez utiliser la fonction WhoAmI
Créez un fichier texte nommé
CommonFunctions.ps1
dans votre dossierscripts
.Copiez et collez la définition de fonction suivante dans
CommonFunctions.ps1
.function Get-WhoAmI{ $WhoAmIRequest = @{ Uri = $baseURI + 'WhoAmI' Method = 'Get' Headers = $baseHeaders } Invoke-RestMethod @WhoAmIRequest }
Notes
Cette définition de fonction utilise une technique appelée Splatting. Le Splatting rend vos commandes plus courtes et plus faciles à lire, car il transmet une collection de valeurs de paramètres à une commande en tant qu’unité.
Enregistrez le fichier
CommonFunctions.ps1
.Modifiez le fichier pour qu’il ressemble au script suivant :
test.ps1
. $PSScriptRoot\Core.ps1 . $PSScriptRoot\CommonFunctions.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change to your organization # Invoke WhoAmI Function Get-WhoAmI | ConvertTo-Json
N’oubliez pas de modifier la valeur
https://yourorg.crm.dynamics.com/
pour qu’elle corresponde à l’URL de votre environnement.Pour exécuter le script, appuyez sur F5.
La sortie devrait ressembler exactement à ce qu’elle était auparavant.
Créer des fonctions d’opérations de table
Mettons les fonctions pour effectuer des opérations de table courantes dans un fichier nommé TableOperations.ps1
afin que nous puissions les réutiliser.
Créez un fichier texte nommé
TableOperations.ps1
dans votre dossierscripts
.Copiez et collez les définitions de fonction suivantes dans
TableOperations.ps1
.function Get-Records { param ( [Parameter(Mandatory)] [String] $setName, [Parameter(Mandatory)] [String] $query ) $uri = $baseURI + $setName + $query # Header for GET operations that have annotations $getHeaders = $baseHeaders.Clone() $getHeaders.Add('If-None-Match', $null) $getHeaders.Add('Prefer', 'odata.include-annotations="*"') $RetrieveMultipleRequest = @{ Uri = $uri Method = 'Get' Headers = $getHeaders } Invoke-RestMethod @RetrieveMultipleRequest } function New-Record { param ( [Parameter(Mandatory)] [String] $setName, [Parameter(Mandatory)] [hashtable] $body ) $postHeaders = $baseHeaders.Clone() $postHeaders.Add('Content-Type', 'application/json') $CreateRequest = @{ Uri = $baseURI + $setName Method = 'Post' Headers = $postHeaders Body = ConvertTo-Json $body } Invoke-RestMethod @CreateRequest -ResponseHeadersVariable rh | Out-Null $url = $rh['OData-EntityId'] $selectedString = Select-String -InputObject $url -Pattern '(?<=\().*?(?=\))' return [System.Guid]::New($selectedString.Matches.Value.ToString()) } function Get-Record { param ( [Parameter(Mandatory)] [String] $setName, [Parameter(Mandatory)] [Guid] $id, [String] $query ) $uri = $baseURI + $setName $uri = $uri + '(' + $id.Guid + ')' + $query $getHeaders = $baseHeaders.Clone() $getHeaders.Add('If-None-Match', $null) $getHeaders.Add('Prefer', 'odata.include-annotations="*"') $RetrieveRequest = @{ Uri = $uri Method = 'Get' Headers = $getHeaders } Invoke-RestMethod @RetrieveRequest } function Update-Record { param ( [Parameter(Mandatory)] [String] $setName, [Parameter(Mandatory)] [Guid] $id, [Parameter(Mandatory)] [hashtable] $body ) $uri = $baseURI + $setName $uri = $uri + '(' + $id.Guid + ')' # Header for Update operations $updateHeaders = $baseHeaders.Clone() $updateHeaders.Add('Content-Type', 'application/json') $updateHeaders.Add('If-Match', '*') # Prevent Create $UpdateRequest = @{ Uri = $uri Method = 'Patch' Headers = $updateHeaders Body = ConvertTo-Json $body } Invoke-RestMethod @UpdateRequest } function Remove-Record { param ( [Parameter(Mandatory)] [String] $setName, [Parameter(Mandatory)] [Guid] $id ) $uri = $baseURI + $setName $uri = $uri + '(' + $id.Guid + ')' $DeleteRequest = @{ Uri = $uri Method = 'Delete' Headers = $baseHeaders } Invoke-RestMethod @DeleteRequest }
Pour obtenir des informations sur la façon de composer ces requêtes, consultez les articles suivants :
Enregistrez le fichier
TableOperations.ps1
.Copiez et collez le code suivant dans le fichier
test.ps1
.. $PSScriptRoot\Core.ps1 . $PSScriptRoot\CommonFunctions.ps1 . $PSScriptRoot\TableOperations.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change to your organization # Retrieve Records Write-Host 'Retrieve first three account records:' (Get-Records ` -setName accounts ` -query '?$select=name&$top=3').value | Format-Table -Property name, accountid # Create a record Write-Host 'Create an account record:' $newAccountID = New-Record ` -setName accounts ` -body @{ name = 'Example Account'; accountcategorycode = 1 # Preferred } Write-Host "Account with ID $newAccountID created" # Retrieve a record Write-Host 'Retrieve the created record:' Get-Record ` -setName accounts ` -id $newAccountID.Guid '?$select=name,accountcategorycode' | Format-List -Property name, accountid, accountcategorycode, accountcategorycode@OData.Community.Display.V1.FormattedValue # Update a record Write-Host 'Update the record:' $updateAccountData = @{ name = 'Updated Example account'; accountcategorycode = 2; #Standard } Update-Record ` -setName accounts ` -id $newAccountID.Guid ` -body $updateAccountData Write-Host 'Retrieve the updated the record:' Get-Record ` -setName accounts ` -id $newAccountID.Guid ` -query '?$select=name,accountcategorycode' | Format-List -Property name, accountid, accountcategorycode, accountcategorycode@OData.Community.Display.V1.FormattedValue # Delete a record Write-Host 'Delete the record:' Remove-Record ` -setName accounts ` -id $newAccountID.Guid Write-Host "The account with ID $newAccountID was deleted"
N’oubliez pas de modifier la valeur
https://yourorg.crm.dynamics.com/
pour qu’elle corresponde à l’URL de votre environnement.Pour exécuter le script, appuyez sur F5.
Le résultat pourrait ressembler à ce résultat :
PS C:\scripts> . 'C:\scripts\test.ps1' Retrieve first three account records: name accountid ---- --------- Fourth Coffee (sample) d2382248-cd99-ee11-be37-000d3a9b7981 Litware, Inc. (sample) d4382248-cd99-ee11-be37-000d3a9b7981 Adventure Works (sample) d6382248-cd99-ee11-be37-000d3a9b7981 Create an account record: Account with ID a2c3ebc2-39a8-ee11-be37-000d3a8e8e07 created Retrieve the created record: name : Example Account accountid : a2c3ebc2-39a8-ee11-be37-000d3a8e8e07 accountcategorycode : 1 accountcategorycode@OData.Community.Display.V1.FormattedValue : Preferred Customer Update the record: Retrieve the updated the record: name : Updated Example account accountid : a2c3ebc2-39a8-ee11-be37-000d3a8e8e07 accountcategorycode : 2 accountcategorycode@OData.Community.Display.V1.FormattedValue : Standard Delete the record: The account with ID a2c3ebc2-39a8-ee11-be37-000d3a8e8e07 was deleted
Gérer les exceptions
Jusqu’à présent, dans cet article, vous avez copié et collé le code qui vous est fourni. Mais lorsque vous commencez à écrire et à utiliser vos propres fonctions, vous pouvez rencontrer des erreurs. Lorsque ces erreurs se produisent, elles peuvent provenir de Dataverse ou de votre script.
Ajoutez une fonction d’assistance qui peut aider à détecter la source des erreurs et à extraire les détails pertinents des erreurs renvoyées par Dataverse.
Ajoutez la fonction suivante au fichier :
Invoke-DataverseCommands
Core.ps1
function Invoke-DataverseCommands { param ( [Parameter(Mandatory)] $commands ) try { Invoke-Command $commands } catch [Microsoft.PowerShell.Commands.HttpResponseException] { Write-Host "An error occurred calling Dataverse:" -ForegroundColor Red $statuscode = [int]$_.Exception.StatusCode; $statusText = $_.Exception.StatusCode Write-Host "StatusCode: $statuscode ($statusText)" # Replaces escaped characters in the JSON [Regex]::Replace($_.ErrorDetails.Message, "\\[Uu]([0-9A-Fa-f]{4})", {[char]::ToString([Convert]::ToInt32($args[0].Groups[1].Value, 16))} ) } catch { Write-Host "An error occurred in the script:" -ForegroundColor Red $_ } }
La fonction
Invoke-DataverseCommands
utilise l’applet de commande Invoke-Command pour traiter un ensemble de commandes dans un bloc try/catch. Toutes les erreurs renvoyées par Dataverse sont des erreurs HttpResponseException, donc le premier bloccatch
écrit un messageAn error occurred calling Dataverse:
au terminal avec les données d’erreur JSON.Les données JSON dans
$_.ErrorDetails.Message
contiennent des caractères Unicode d’échappement. Par exemple :\u0026
au lieu de&
et\u0027
au lieu de'
. Cette fonction inclut du code qui remplace ces caractères par les caractères sans échappement afin qu’ils correspondent exactement aux erreurs que vous voyez ailleurs.Sinon, les erreurs sont réécrites dans la fenêtre du terminal avec un message :
An error occurred in the script:
Enregistrez le fichier
Core.ps1
.Modifiez le fichier pour ajouter le script suivant qui utilise une valeur de paramètre non valide.
test.ps1
setName
Le paramètre doit êtreaccount
.accounts
Cette erreur est courante.. $PSScriptRoot\Core.ps1 . $PSScriptRoot\CommonFunctions.ps1 . $PSScriptRoot\TableOperations.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change this Invoke-DataverseCommands { # Retrieve Records Write-Host 'Retrieve first three account records:' (Get-Records ` -setName account ` -query '?$select=name&$top=3').value | Format-Table -Property name, accountid }
N’oubliez pas de modifier la valeur
https://yourorg.crm.dynamics.com/
pour qu’elle corresponde à l’URL de votre environnement.Pour exécuter le script, appuyez sur F5.
Le résultat pourrait ressembler à ce résultat :
PS C:\scripts> . 'C:\scripts\test.ps1' Retrieve first three account records: An error occurred calling Dataverse: StatusCode: 404 (NotFound) { "error": { "code": "0x80060888", "message": "Resource not found for the segment 'account'." } }
Modifiez le fichier
test.ps1
pour générer une erreur de script dans le blocInvoke-DataverseCommands
:Invoke-DataverseCommands { throw 'A script error' }
Pour exécuter le script, appuyez sur F5.
Le résultat devrait être presque le même que s’il n’était pas inclus dans le bloc
Invoke-DataverseCommands
:PS C:\scripts> . 'C:\scripts\test.ps1' An error occurred in the script: Exception: C:\scripts\test.ps1:8:4 Line | 8 | throw 'A script error' | ~~~~~~~~~~~~~~~~~~~~~~ | A script error
Gérer les limites de protection de service Dataverse
Les limites de l’API de protection des services Dataverse permettent de garantir que Dataverse propose une disponibilité et des performances constantes. Lorsque les applications clientes font des demandes extraordinaires sur les ressources du serveur à l’aide de l’API Web, Dataverse renvoie 429 Too Many Requests des erreurs et les applications clientes doivent suspendre leurs opérations pendant la durée spécifiée dans l’en-tête Retry-After.
L’applet de commande Invoke-RestMethod PowerShell Paramètre MaximumRetryCount spécifie combien de fois PowerShell réessaye une demande lorsqu’un code d’échec est compris entre 400 et 599 inclus ou que le code 304 est reçu. Cela signifie que PowerShell réessaye en cas d’erreur de type 429 de protection de services Dataverse lorsque vous incluez une valeur pour ce paramètre. Le paramètre MaximumRetryCount
peut être utilisé avec RetryIntervalSec pour spécifier le nombre de secondes à attendre. La valeur par défaut est 5 secondes. Si la réponse à l’erreur inclut un en-tête Retry-After
pour une erreur 429, comme les erreurs de protection de services Dataverse se produisent, cette valeur est utilisée à la place.
Vous ne rencontrerez peut-être jamais d’erreur de limite de protection de service pendant que vous apprenez à utiliser l’API web Dataverse avec PowerShell. Cependant, les scripts que vous écrivez peuvent envoyer un grand nombre de requêtes qui génèrent des erreurs. Découvrez donc comment les gérer au mieux à l’aide de PowerShell.
Si vous ajoutez le paramètre MaximumRetryCount
à chaque appel Dataverse en utilisant Invoke-RestMethod
, PowerShell réessaye un large éventail d’erreurs. Réessayer chaque erreur ralentit vos scripts, en particulier lors du développement et des tests. Vous devrez attendre 10 à 15 secondes à chaque fois qu’une erreur se produit, selon le nombre de tentatives que vous spécifiez. Une approche alternative consiste à encapsuler la Invoke-RestMethod
dans votre propre méthode qui gère les tentatives pour des erreurs spécifiques.
La fonction suivante prend un objet de table de hachage comme paramètre obligatoire et un indicateur booléen Invoke-ResilientRestMethod
pour indiquer s’il faut ou non renvoyer l’en-tête réponse. request
returnHeader
Lorsque $returnHeader
est vrai, il envoie la requête à l’aide de la Invoke-RestMethod
commande avec le paramètre ResponseHeadersVariable pour capturer les en-têtes renvoyés. La fonction utilise Out-Null donc la sortie qui représente le corps réponse vide n’est pas renvoyée avec la fonction. Sinon, la fonction envoie la requête en utilisant Invoke-RestMethod
l’objet request
et renvoie le corps réponse.
Si Invoke-RestMethod
échoue avec une erreur 429, elle vérifie si l’objet request
a une propriété MaximumRetryCount
. Si la fonction réussit, elle crée une MaximumRetryCount
propriété définie sur 3
. La Invoke-RestMethod
relance est ensuite effectuée à l’aide de l’objet de requête et de la valeur d’en-tête Retry-After
réponse. Si l’indicateur returnHeader
est défini sur True, il renvoie l’en-tête de réponse. Si Invoke-RestMethod
échoue avec une autre erreur, elle renvoie l’exception.
function Invoke-ResilientRestMethod {
param (
[Parameter(Mandatory)]
$request,
[bool]
$returnHeader
)
try {
if ($returnHeader) {
Invoke-RestMethod @request -ResponseHeadersVariable rhv | Out-Null
return $rhv
}
Invoke-RestMethod @request
}
catch [Microsoft.PowerShell.Commands.HttpResponseException] {
$statuscode = $_.Exception.Response.StatusCode
# 429 errors only
if ($statuscode -eq 'TooManyRequests') {
if (!$request.ContainsKey('MaximumRetryCount')) {
$request.Add('MaximumRetryCount', 3)
# Don't need - RetryIntervalSec
# When the failure code is 429 and the response includes the Retry-After property in its headers,
# the cmdlet uses that value for the retry interval, even if RetryIntervalSec is specified
}
# Will attempt retry up to 3 times
if ($returnHeader) {
Invoke-RestMethod @request -ResponseHeadersVariable rhv | Out-Null
return $rhv
}
Invoke-RestMethod @request
}
else {
throw $_
}
}
catch {
throw $_
}
}
Vous pouvez utiliser une fonction similaire dans vos fonctions réutilisables. Lorsque les fonctions doivent renvoyer des valeurs de l’en-tête de la réponse, elles doivent définir la valeur returnHeader
sur $true
. Par exemple, la fonction suivante New-Record
modifie l’exemple de fonction dans Fonctions d’opérations de création de table pour l’utiliser Invoke-ResilientRestMethod
au lieu de Invoke-RestMethod
directement.
function New-Record {
param (
[Parameter(Mandatory)]
[String]
$setName,
[Parameter(Mandatory)]
[hashtable]
$body
)
$postHeaders = $baseHeaders.Clone()
$postHeaders.Add('Content-Type', 'application/json')
$CreateRequest = @{
Uri = $environmentUrl + 'api/data/v9.2/' + $setName
Method = 'Post'
Headers = $postHeaders
Body = ConvertTo-Json $body
}
# Before:
# Invoke-RestMethod @CreateRequest -ResponseHeadersVariable rh | Out-Null
# After:
$rh = Invoke-ResilientRestMethod -request $CreateRequest -returnHeader $true
$url = $rh['OData-EntityId']
$selectedString = Select-String -InputObject $url -Pattern '(?<=\().*?(?=\))'
return [System.Guid]::New($selectedString.Matches.Value.ToString())
}
Sinon, Invoke-ResilientRestMethod
peut remplacer le Invoke-RestMethod
comme indiqué dans cet exemple Get-Record
:
function Get-Record {
param (
[Parameter(Mandatory)]
[String]
$setName,
[Parameter(Mandatory)]
[Guid]
$id,
[String]
$query
)
$uri = $environmentUrl + 'api/data/v9.2/' + $setName
$uri = $uri + '(' + $id.Guid + ')' + $query
$getHeaders = $baseHeaders.Clone()
$getHeaders.Add('If-None-Match', $null)
$getHeaders.Add('Prefer', 'odata.include-annotations="*"')
$RetrieveRequest = @{
Uri = $uri
Method = 'Get'
Headers = $getHeaders
}
# Before:
# Invoke-RestMethod @RetrieveRequest
# After:
Invoke-ResilientRestMethod $RetrieveRequest
}
La seule différence est que vous transmettez la table de hachage ($RetrieveRequest
) à la méthode au lieu d’utiliser le splatting (@RetrieveRequest
). Sinon, vous obtenez une erreur de script : A parameter cannot be found that matches parameter name 'Headers'.
Déboguer avec Fiddler
Fiddler est un proxy de débogage Web utilisé pour afficher le trafic HTTP sur votre ordinateur. L’affichage de ces données est utile lors du débogage des scripts. Par défaut, les requêtes et réponses HTTP envoyées à l’aide de l’applet de commande Invoke-RestMethod ne sont pas visibles lorsque vous utilisez Fiddler.
Pour afficher le trafic HTTP dans Fiddler, définissez le Invoke-RestMethod
paramètre Proxy sur l’URL configurée comme proxy Fiddler sur votre ordinateur local. Par défaut, l’URL est http://127.0.0.1:8888
. Votre URL peut être différente.
Par exemple, si vous appelez la fonction WhoAmI avec le paramètre -Proxy
défini pendant que Fiddler capture le trafic :
Invoke-RestMethod `
-Uri ($environmentUrl + 'api/data/v9.2/WhoAmI') `
-Method Get `
-Headers $baseHeaders `
-Proxy 'http://127.0.0.1:8888'
Dans Fiddler, vous pouvez voir tous les détails :
GET https://yourorg.api.crm.dynamics.com/api/data/v9.2/WhoAmI HTTP/1.1
Host: yourorg.api.crm.dynamics.com
OData-MaxVersion: 4.0
Accept: application/json
Authorization: Bearer [REDACTED]
OData-Version: 4.0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.22631; en-US) PowerShell/7.4.0
Accept-Encoding: gzip, deflate, br
HTTP/1.1 200 OK
Cache-Control: no-cache
Allow: OPTIONS,GET,HEAD,POST
Content-Type: application/json; odata.metadata=minimal
Expires: -1
Vary: Accept-Encoding
x-ms-service-request-id: 7341c0c1-3343-430b-98ea-292567ed4776
Set-Cookie: ARRAffinity=f60cbee43b7af0a5f322e7ce57a018546ed978f67f0c11cbb5e15b02ddb091a915134d20c556b0b34b9b6ae43ec3f5dcdad61788de889ffc592af7aca85fc1c508DC0FC94CB062A12107345846; path=/; secure; HttpOnly
Set-Cookie: ReqClientId=4fc95009-0b3d-4a19-b223-0d80745636ac; expires=Sun, 07-Jan-2074 21:10:42 GMT; path=/; secure; HttpOnly
Set-Cookie: orgId=648e8efd-db86-466e-a5bc-a4d5eb9c52d4; expires=Sun, 07-Jan-2074 21:10:42 GMT; path=/; secure; HttpOnly
x-ms-service-request-id: 1ee13aa7-47f3-4a75-95fa-2916775a1f79
Strict-Transport-Security: max-age=31536000; includeSubDomains
REQ_ID: 1ee13aa7-47f3-4a75-95fa-2916775a1f79
CRM.ServiceId: framework
AuthActivityId: 0b562cc3-56f6-44f0-a26e-4039cfc4be6a
x-ms-dop-hint: 48
x-ms-ratelimit-time-remaining-xrm-requests: 1,200.00
x-ms-ratelimit-burst-remaining-xrm-requests: 5999
OData-Version: 4.0
X-Source: 110212218438874147222728177124203420477168182861012399121919014511175711948418152
Public: OPTIONS,GET,HEAD,POST
Set-Cookie: ARRAffinity=f60cbee43b7af0a5f322e7ce57a018546ed978f67f0c11cbb5e15b02ddb091a915134d20c556b0b34b9b6ae43ec3f5dcdad61788de889ffc592af7aca85fc1c508DC0FC94CB062A12107345846; path=/; secure; HttpOnly
X-Source: 2302101791355821068628523819830862152291172232072372448021147103846182145238216119
Date: Sun, 07 Jan 2024 21:10:42 GMT
Content-Length: 277
{"@odata.context":"https://yourorg.api.crm.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.WhoAmIResponse","BusinessUnitId":"1647bf36-e90a-4c4d-9b61-969d57ce7a66","UserId":"24e34f5e-7f1a-43fe-88da-7e4b862d51ad","OrganizationId":"648e8efd-db86-466e-a5bc-a4d5eb9c52d4"}
Si Fiddler n’est pas en cours d’exécution, vous obtenez une erreur :
Invoke-RestMethod: C:\scripts\test.ps1:8:1
Line |
8 | Invoke-RestMethod `
| ~~~~~~~~~~~~~~~~~~~
| No connection could be made because the target machine actively refused it.
Si vous choisissez d’acheminer tous vos appels via une seule fonction, telle que celle décrite dans la section Invoke-RestMethod
Gérer les limites de protection des services Invoke-ResilientRestMethod
, vous pouvez définir certaines variables dans le fichier pour configurer cette option à un seul emplacement. Dataverse Core.ps1
# <a name="set-to-true-only-while-debugging-with-fiddler"></a>Set to true only while debugging with Fiddler
$debug = $true
# <a name="set-this-value-to-the-fiddler-proxy-url-configured-on-your-computer"></a>Set this value to the Fiddler proxy URL configured on your computer
$proxyUrl = 'http://127.0.0.1:8888'
Dans votre fonction centralisée, vous pouvez définir le paramètre avec splatting et utiliser le table de hachage uniquement lors du débogage avec Fiddler. -Proxy
$request
function Invoke-ResilientRestMethod {
param (
[Parameter(Mandatory)]
$request,
[bool]
$returnHeader
)
if ($debug) {
$request.Add('Proxy', $proxyUrl)
}
...
Découvrir comment capturer le trafic Web avec Fiddler
Télécharger le document $metadata CSDL de l’API web Dataverse
Les métadonnées du langage CSDL (Common Schema Definition Language) sont la source de vérité sur les fonctionnalités de l’API Web. Dataverse Vous pouvez l’afficher dans un navigateur, mais il vous sera peut-être plus facile de télécharger le fichier et de l’afficher dans Visual Studio Code. Le script suivant est une version modifiée du script introduit dans Démarrage rapide : API web avec PowerShell. La différence est qu’il utilise l’applet de commande Invoke-WebRequest, qui est plus appropriée pour télécharger un document XML.
$environmentUrl = 'https://yourorg.crm.dynamics.com/' # change to your organization
$writeFileTo = 'C:\temp\yourorg.xml' # change to your organization
## <a name="login-if-not-already-logged-in"></a>Login if not already logged in
if ($null -eq (Get-AzTenant -ErrorAction SilentlyContinue)) {
Connect-AzAccount | Out-Null
}
# <a name="get-an-access-token"></a>Get an access token
$token = (Get-AzAccessToken -ResourceUrl $environmentUrl).Token
# <a name="common-headers"></a>Common headers
$xmlHeaders = @{
'Authorization' = 'Bearer ' + $token
'Accept' = 'application/xml'
'OData-MaxVersion' = '4.0'
'OData-Version' = '4.0'
}
$doc = [xml](Invoke-WebRequest `
-Uri ($environmentUrl + 'api/data/v9.2/$metadata?annotations=true') `
-Method 'Get' `
-Headers $xmlHeaders ).Content
$StringWriter = New-Object System.IO.StringWriter
$XmlWriter = New-Object System.XMl.XmlTextWriter $StringWriter
$xmlWriter.Formatting = 'indented'
$xmlWriter.Indentation = 2
$doc.WriteContentTo($XmlWriter)
$XmlWriter.Flush()
$StringWriter.Flush()
Set-Content -Path $writeFileTo -Value $StringWriter.ToString()
code $writeFileTo
- Copiez le script.
- Modifiez les variables
$environmentUrl
et$writeFileTo
en fonction de vos besoins. - Exécutez le script dans Visual Studio Code.
Le document $metadata CSDL de l’API Web s’ouvre dans Dataverse Code. Visual Studio
Vous pourriez recevoir une notification indiquant : Pour des raisons de performances, les symboles de document sont limités à 5 000 éléments. Si une nouvelle limite est définie, Fermer et rouvrez ce fichier pour recalculer les symboles de document.
La notification donne la possibilité de modifier la Visual Studio limite d’extension du code XML xml.symbols.maxItemsComputed
. Pour la plupart des documents de métadonnées CSDL de l’API Web, la définition de la limite à devrait être suffisante. Dataverse 500000
Résolution des problèmes
Cette section contient des conseils sur les problèmes que vous pourriez rencontrer.
Boîte de dialogue d’erreur : connectez ENOENT\\.\pipe\<RANDOM_text> avec le bouton Ouvrir ’launch.json’
Cette erreur peut se produire lors du débogage avec Visual Studio Code. Pour résoudre l’erreur :
- Sélectionnez Afficher > Palette de commandes... dans le menu Visual Studio Code ou appuyez sur Ctrl+Maj+P.
- Saisissez
restart
et sélectionnezPowershell: Restart session
. Consultez PowerShell/vscode-powershell Problème GitHub 4332 pour plus d’informations.
Étapes suivantes
En savoir plus sur les fonctionnalités de l’API web Dataverse en comprenant les documents de service.
Examinez et exécutez un exemple de code.