PowerShell und Visual Studio Code in der Dataverse-Web-API verwenden
Dieser Artikel geht näher auf die Themen im Artikel Schnellstart-Web-API mit PowerShell ein und beschreibt erweiterte Funktionen, die mithilfe von PowerShell und Visual Studio Code mit der Dataverse-Web-API für Folgendes verwendet werden können:
- Wiederverwendbare Funktionen erstellen
- Verarbeiten von Ausnahmen
- Dataverse-Dienstschutzgrenzwerte verwalten
- Debuggen mithilfe von Fiddler
- Das CSDL-$metadata-Dokument für die Dataverse-Web-API herunterladen
Hinweis
Die Anweisungen in diesem Artikel sollten für Windows, Linux und macOS funktionieren. Die Schritte wurden jedoch nur mit Windows getestet. Wenn Änderungen erforderlich sind, teilen Sie uns dies über den Abschnitt Feedback am Ende dieses Artikels mit.
Anforderungen
Für den Inhalt dieses Artikels gelten dieselben Voraussetzungen wie für den Artikel Schnellstart-Web-API mit PowerShell.
Installieren Sie Folgendes oder überprüfen Sie, ob es vorhanden ist
Installieren Sie Visual Studio Code. Siehe Visual Studio Code herunterladen
Installieren Sie die PowerShell-Erweiterung für Visual Studio Code. Siehe PowerShell für Visual Studio Code
Installieren Sie PowerShell 7.4 oder höher. Siehe PowerShell unter Windows, Linux und macOS installieren
Installieren Sie die Az-PowerShell-Modulversion 11.1.0 oder höher. Siehe Azure PowerShell richtig installieren
Verwenden Sie
Update-Module -Name Az -Force
, um eine bestehende Installation auf die neueste Version zu aktualisieren
Überprüfen der Installation
Öffnen Sie Visual Studio Code.
Wählen Sie im Terminal-Menü Neues Terminal aus.
Wählen Sie im Visual Studio Code-Navigationsbereich das -Symbol für die PowerShell-Erweiterung aus.
Kopieren und fügen Sie das folgende Skript im Terminalfenster von Visual Studio Code aus:
Write-Host 'PowerShell Version:'$PSVersionTable.PSVersion.ToString() Write-Host 'PowerShell Az version:'(Get-InstalledModule Az).Version
Drücken Sie die Eingabetaste. Die Ausgabe sollte wie folgt aussehen:
PowerShell Version: 7.4.0 PowerShell Az version: 11.1.0
Wenn Sie keine derartigen Ergebnisse sehen, installieren oder aktualisieren Sie die Voraussetzungen.
Darüber hinaus brauchen Sie
- Ein gültiges Benutzerkonto für eine Dataverse-Umgebung
- Die URL zur Dataverse-Umgebung, mit der Sie eine Verbindung herstellen möchten. Unter Entwicklerressourcen anzeigen erfahren Sie, wie Sie ihn finden. Sie sieht ungefähr so aus:
https://yourorg.crm.dynamics.com/
, wobeiyourorg.crm
anders ist. - Grundlegende Kenntnisse über die PowerShell-Skriptsprache
Wiederverwendbare Funktionen erstellen
Schnellstart Web-API mit PowerShell bot eine Einführung in die Authentifizierung und den Aufruf der WhoAmI-Funktion mit Visual Studio Code. Für einen Ad-hoc-Test eines oder mehrerer Vorgänge ist dieser Ansatz möglicherweise ausreichend. Wenn Ihre Skripte jedoch komplexer werden, müssen Sie möglicherweise immer wieder denselben Code eingeben.
In diesem Abschnitt beginnen wir mit der Erstellung einer Reihe wiederverwendbarer Funktionen in separaten Dateien, auf die wir über Dot-Sourcing zugreifen können. Verwenden Sie Dot-Sourcing, um eine Datei mit PowerShell-Skripten zu laden, die Funktionen und Variablen enthalten können, die Teil des lokalen Skriptbereichs werden.
Tipp
Vollständig dokumentierte Definitionen dieser Funktionen und mehr finden Sie in unserem PowerApps-Beispiel-Repository auf GitHub unter PowerApps-Samples/dataverse/webapi/PS/
Eine Verbindungsfunktion erstellen
Fügen wir den Code zur Authentifizierung in Dataverse in eine Funktion namens Connect
in einer Datei namens Core.ps1
ein, damit wir ihn in einer einzigen Codezeile wiederverwenden können.
Erstellen Sie einen Ordner. In diesem Beispiel erstellen wir einen Ordner in
C:\scripts
.Öffnen Sie den Skriptordner innerhalb von Visual Studio Code.
Erstellen Sie im Skriptordner eine Textdatei mit dem Namen
Core.ps1
.Kopieren Sie die folgende
Connect
-Funktion und fügen Sie sie dann in dieCore.ps1
-Datei ein.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/' }
Hinweis
Das Skript fügt die
baseURI
- undbaseHeaders
-Variablen mithilfe des$global
Bereichsmodifizierer zum globalen Kontext hinzu, sodass sie für andere Skripte in derselben Sitzung verfügbar sind.Erstellen Sie eine weitere Textdatei im Visual Studio Codenamen
test.ps1
in Ihremscripts
Ordner.Kopieren Sie das folgende Skript in die
test.ps1
-Datei:. $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
oben in der Datei verwendet Dot Sourcing , um das Skript anzuweisen, den Inhalt dieser Datei zu laden.Denken Sie daran,
https://yourorg.crm.dynamics.com/
so zu ändern, dass es der URL für Ihr Umgebung entspricht.Um das Skript auszuführen, drücken Sie F5.
Die Ausgabe könnte ungefähr wie diese aussehen:
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" }
Eine WhoAmI-Funktion erstellen
Fügen wir den Code zum Aufrufen der WhoAmI-Funktion in eine Funktion namens Get-WhoAmI
in einer Datei mit dem Namen CommonFunctions.ps1
ein, damit wir jedes Mal, wenn wir die WhoAmI-Funktion verwenden möchten, nur elf und nicht 100 Zeichen eingeben müssen
Erstellen Sie in Ihrem
scripts
-Ordner eine neue Textdatei namensCommonFunctions.ps1
.Kopieren Sie die folgende Funktionsdefinition und fügen Sie sie in die
CommonFunctions.ps1
ein.function Get-WhoAmI{ $WhoAmIRequest = @{ Uri = $baseURI + 'WhoAmI' Method = 'Get' Headers = $baseHeaders } Invoke-RestMethod @WhoAmIRequest }
Hinweis
Diese Funktionsdefinition verwendet eine Technik namens Splatting. Durch Splatting werden Ihre Befehle kürzer und leichter lesbar, da eine Sammlung von Parameterwerten als Einheit an einen Befehl übergeben wird.
Speichern Sie die Datei
CommonFunctions.ps1
.Ändern Sie die Datei
test.ps1
so, dass sie wie das folgende Skript aussieht:. $PSScriptRoot\Core.ps1 . $PSScriptRoot\CommonFunctions.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change to your organization # Invoke WhoAmI Function Get-WhoAmI | ConvertTo-Json
Denken Sie daran, den
https://yourorg.crm.dynamics.com/
-Wert so zu ändern, dass er mit der URL für Ihre Umgebung übereinstimmt.Um das Skript auszuführen, drücken Sie F5.
Die Ausgabe sollte genauso aussehen wie zuvor.
Tabellenvorgangsfunktionen erstellen
Legen wir Funktionen zum Ausführen allgemeiner Tabellenvorgänge in eine Datei mit dem Namen TableOperations.ps1
fest, damit wir sie wiederverwenden können.
Erstellen Sie in Ihrem
scripts
-Ordner eine neue Textdatei namensTableOperations.ps1
.Kopieren Sie die folgende Funktionsdefinitionen und fügen Sie sie in die
TableOperations.ps1
ein.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 }
Informationen zum Verfassen dieser Anforderungen finden Sie in den folgenden Artikeln:
Speichern Sie die Datei
TableOperations.ps1
.Kopieren Sie den folgenden Code und fügen Sie ihn dann in die
test.ps1
-Datei ein.. $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"
Denken Sie daran, den
https://yourorg.crm.dynamics.com/
-Wert so zu ändern, dass er mit der URL für Ihre Umgebung übereinstimmt.Um das Skript auszuführen, drücken Sie F5.
Die Ausgabe könnte ungefähr wie diese aussehen:
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
Verarbeiten von Ausnahmen
Bisher haben Sie in diesem Artikel den für Sie bereitgestellten Code kopiert und eingefügt. Wenn Sie jedoch beginnen, Ihre eigenen Funktionen zu schreiben und zu verwenden, können Fehler auftreten. Wenn diese Fehler auftreten, können sie von Dataverse oder Ihrem Skript herrühren.
Fügen Sie eine Hilfsfunktion hinzu, die beim Erkennen der Fehlerquelle helfen und relevante Details aus den von Dataverse zurückgegebenen Fehlern extrahieren kann.
Fügen Sie der
Invoke-DataverseCommands
Datei die folgendeCore.ps1
Funktion hinzu: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 $_ } }
Die
Invoke-DataverseCommands
-Funktion verwendet das Invoke-Command-Cmdlet, um eine Reihe von Befehlen innerhalb eines try/catch-Blocks zu verarbeiten. Alle von Dataverse zurückgegebenen Fehler sind HttpResponseException-Fehler, daher schreibt der erstecatch
-Block eineAn error occurred calling Dataverse:
-Nachricht mit den JSON-Fehlerdaten an das Terminal.Die JSON-Daten in
$_.ErrorDetails.Message
enthalten einige maskierte Unicode-Zeichen. Zum Beispiel:\u0026
statt&
und\u0027
statt'
. Diese Funktion enthält Code, der diese Zeichen durch unmaskierte Zeichen ersetzt, sodass sie genau mit Fehlern übereinstimmen, die Sie an anderer Stelle sehen.Andernfalls werden die Fehler in das Terminalfenster zurückgeschrieben und zwar mit einer Meldung
An error occurred in the script:
Speichern Sie die Datei
Core.ps1
.Bearbeiten Sie die
test.ps1
Datei, um das folgende Skript hinzuzufügen, das einen ungültigensetName
Parameterwert verwendet. Deraccount
Parameter sollteaccounts
sein. Dieser Fehler tritt häufig auf.. $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 }
Denken Sie daran, den
https://yourorg.crm.dynamics.com/
-Wert so zu ändern, dass er mit der URL für Ihre Umgebung übereinstimmt.Um das Skript auszuführen, drücken Sie F5.
Die Ausgabe könnte ungefähr wie diese aussehen:
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'." } }
Bearbeiten Sie die
test.ps1
-Datei, um einen Skriptfehler innerhalb desInvoke-DataverseCommands
-Blocks auszulösen:Invoke-DataverseCommands { throw 'A script error' }
Um das Skript auszuführen, drücken Sie F5.
Die Ausgabe sollte fast die gleiche sein, als wäre sie nicht im
Invoke-DataverseCommands
-Block enthalten: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
Dataverse-Dienstschutzgrenzwerte verwalten
Die Dataverse-Dienstschutz-API-Grenzwerte helfen dabei, sicherzustellen, dass Dataverse für konsistente Verfügbarkeit und Leistung sorgt. Wenn Client-Anwendungen unter Verwendung der Web-API außerordentliche Anforderungen an die Serverressourcen stellen, Dataverse wird der Fehler 429 Too Many Requests zurückgegeben, und Client-Anwendungen müssen ihre Vorgänge für die im Retry-After-Header angegebene Dauer anhalten.
Der PowerShell MaximumRetryCount-Parameter des Invoke-RestMethod-Cmdlet gibt an, wie oft PowerShell eine Anforderung wiederholt, wenn ein Fehlercode zwischen 400 und einschließlich 599 oder 304 eingeht. Dies bedeutet, dass PowerShell Dataverse-Dienstschutz-429-Fehler erneut versucht, wenn Sie einen Wert für diesen Parameter angeben. Der MaximumRetryCount
-Parameter kann mit RetryIntervalSec verwendet werden, um die Anzahl der zu wartenden Sekunden anzugeben. Der Standardwert sind fünf Sekunden. Wenn die Fehlerantwort einen Retry-After
-Header für einen 429-Fehler enthält, was bei Dataverse-Dienstschutzfehlern der Fall ist, wird stattdessen dieser Wert verwendet.
Es kann sein, dass nie ein Dienstschutzgrenzwertfehler auftritt, während Sie sich mit der Dataverse-Web-API mit PowerShell vertraut machen. Die von Ihnen geschriebenen Skripts senden jedoch möglicherweise eine große Anzahl von Anfragen, die Fehler verursachen. Informieren Sie sich daher, wie Sie diese am besten mit PowerShell verwalten können.
Wenn Sie den MaximumRetryCount
-Parameter zu jedem Dataverse-Aufruf mit Invoke-RestMethod
hinzufügen, versucht PowerShell eine Vielzahl von Fehlern erneut. Wenn Sie jeden Fehler erneut versuchen, werden Ihre Skripte langsamer, insbesondere beim Entwickeln und Testen. Bei jedem Fehler müssten Sie 10 bis 15 Sekunden warten, je nachdem, wie viele Wiederholungen Sie angeben. Ein alternativer Ansatz besteht darin, Invoke-RestMethod
in Ihre eigene Methode einzuschließen, die Wiederholungsversuche für bestimmte Fehler verwaltet.
Die folgende Invoke-ResilientRestMethod
Funktion verwendet ein request
Hashtabellenobjekt als obligatorischen Parameter und ein boolesch returnHeader
Flag, um anzugeben, ob der Header Antwort zurückgegeben werden soll oder nicht. Wenn $returnHeader
true ist, wird die Anforderung mithilfe des Invoke-RestMethod
Befehls mit dem Parameter ResponseHeadersVariable gesendet, um die zurückgegebenen Header zu erfassen. Die Funktion verwendet Out-Null , sodass die Ausgabe, die den leeren Antwort-Textkörper darstellt, nicht mit der Funktion zurückgegeben wird. Andernfalls sendet die Funktion die Anforderung mit dem Invoke-RestMethod
Objekt und gibt den Body Antwort zurück. request
Wenn Invoke-RestMethod
mit einem 429-Fehler fehlschlägt, wird geprüft, ob das request
-Objekt eine MaximumRetryCount
-Eigenschaft hat. Wenn die Funktion erfolgreich ist, erstellt sie eine MaximumRetryCount
Eigenschaft, die auf 3
gesetzt ist. Der Invoke-RestMethod
Aufruf wird dann mit dem Anforderungsobjekt und dem Header-Wert Retry-After
Antwort wiederholt. Wenn die returnHeader
-Kennzeichnung wahr ist, wird der Antwortheader zurückgegeben. Wenn Invoke-RestMethod
mit einem anderen Fehler fehlschlägt, wird die Ausnahme erneut ausgelöst.
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 $_
}
}
Sie können eine ähnliche Funktion in Ihren wiederverwendbaren Funktionen verwenden. Wenn Funktionen Werte aus dem Header der Antwort zurückgeben müssen, müssen sie den returnHeader
-Wert auf $true
setzen. Beispielsweise ändert die folgende New-Record
-Funktion die Beispielfunktion in Tabellenvorgangsfunktionen erstellen so, dass sie Invoke-ResilientRestMethod
anstelle von direkt Invoke-RestMethod
verwendet.
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())
}
Andernfalls kann die Invoke-ResilientRestMethod
die Invoke-RestMethod
wie in diesem Get-Record
-Beispiel gezeigt ersetzen:
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
}
Der einzige Unterschied besteht darin, dass Sie die Hashtabelle ($RetrieveRequest
) an die Methode übergeben, anstatt Splatting (@RetrieveRequest
) zu verwenden. Andernfalls erhalten Sie einen Skriptfehler: A parameter cannot be found that matches parameter name 'Headers'.
Debuggen mithilfe von Fiddler
Fiddler ist ein Web-Debugging-Proxy, der zum Anzeigen des HTTP-Datenverkehrs auf Ihrem Computer verwendet wird. Das Anzeigen dieser Daten ist beim Debuggen von Skripten hilfreich. Standardmäßig sind HTTP-Anfragen und -Antworten, die mit dem Cmdlet „Invoke-RestMethod“ gesendet werden, nicht sichtbar, wenn Sie Fiddler verwenden.
Um HTTP-Verkehr in Fiddler anzuzeigen, legen Sie den Invoke-RestMethod
Proxy-Parameter auf die URL fest, die auf Ihrem lokalen Computer als Fiddler-Proxy konfiguriert ist. Die URL lautet standardmäßig http://127.0.0.1:8888
. Ihre URL kann anders sein.
Wenn Sie beispielsweise die WhoAmI-Funktion mit dem -Proxy
-Parameter aufrufen, während Fiddler Datenverkehr erfasst:
Invoke-RestMethod `
-Uri ($environmentUrl + 'api/data/v9.2/WhoAmI') `
-Method Get `
-Headers $baseHeaders `
-Proxy 'http://127.0.0.1:8888'
In Fiddler können Sie alle Details sehen:
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"}
Wenn Fiddler nicht läuft, erhalten Sie eine Fehlermeldung:
Invoke-RestMethod: C:\scripts\test.ps1:8:1
Line |
8 | Invoke-RestMethod `
| ~~~~~~~~~~~~~~~~~~~
| No connection could be made because the target machine actively refused it.
Wenn Sie alle Ihre Invoke-RestMethod
Anrufe über eine einzige Funktion weiterleiten möchten, wie etwa die unter Invoke-ResilientRestMethod
Dienstschutzgrenzen verwalten beschriebene Dataverse Funktion, können Sie in der Datei einige Variablen festlegen, um diese Option an einer einzigen Stelle zu konfigurieren. 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'
Innerhalb Ihrer zentralisierten Funktion können Sie den -Proxy
Parameter mit Splatting festlegen und $request
Hashtabelle nur beim Debuggen mit Fiddler verwenden.
function Invoke-ResilientRestMethod {
param (
[Parameter(Mandatory)]
$request,
[bool]
$returnHeader
)
if ($debug) {
$request.Add('Proxy', $proxyUrl)
}
...
Erfahren Sie mehr über die Erfassung von Webdatenverkehr mit Fiddler
Das CSDL-$metadata-Dokument für die Dataverse-Web-API herunterladen
Die $metadata der Common Schema Definition Language (CSDL) sind die wahre Quelle der Dataverse Web-API-Funktionen. Sie können sie in einem Browser anzeigen. Eventuell ist es jedoch einfacher, die Datei herunterzuladen und innerhalb von Visual Studio Code anzuzeigen. Das folgende Skript ist eine modifizierte Version des Skripts, das in Schnellstart-Web-API mit PowerShell eingeführt wurde. Der Unterschied besteht darin, dass das Invoke-WebRequest-Cmdlet verwendet wird, das besser zum Herunterladen eines XML-Dokuments geeignet ist.
$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
- Kopieren Sie das Skript.
- Bearbeiten Sie die
$environmentUrl
- und$writeFileTo
-Variablen je nach Ihren Anforderungen. - Führen Sie das Skript im Visual Studio Code aus.
Das Dataverse Web-API-CSDL-$metadata-Dokument wird im Visual Studio Code geöffnet.
Möglicherweise erhalten Sie eine Benachrichtigung mit dem Inhalt: Aus Leistungsgründen sind Dokumentsymbole auf 5.000 Elemente begrenzt. Wenn ein neues Limit festgelegt wird, schließen Sie diese Datei und öffnen Sie sie erneut, um die Dokumentsymbole neu zu berechnen.
Die Benachrichtigung bietet die Möglichkeit, das Limit für die Visual Studio Code-XML-Erweiterung xml.symbols.maxItemsComputed
zu ändern. Für die meisten Dataverse Web-API-CSDL-$metadata-Dokumente sollte es ausreichen, das Limit auf 500000
festzulegen.
Problembehandlung
Dieser Abschnitt enthält einige Hinweise zu Problemen, auf die Sie möglicherweise stoßen.
Fehlerdialog: Verbinden Sie ENOENT\\.\pipe\<RANDOM_text> mit der Schaltfläche „Launch.json öffnen“
Dieser Fehler kann beim Debuggen mit Visual Studio Code auftreten. So beheben Sie den Fehler:
- Wählen Sie Ansicht > Befehlspalette ... aus dem Visual Studio Code-Menü oder drücken Sie Strg+Umschalttaste+P.
- Geben Sie
restart
ein und wählen SiePowershell: Restart session
aus. Weitere Informationen finden Sie unter PowerShell/vscode-powershell-GitHub-Issue 4332.
Nächste Schritte,
Erfahren Sie mehr über Dataverse-Web-API-Funktionen durch Verständnis der Servicedokumente.
Überprüfen Sie den Beispielcode und führen Sie ihn aus.