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. Falls Änderungen erforderlich sind, teilen Sie uns dies bitte ü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 mithilfe 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 mit dem Visual Studio Code namens
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 this # Invoke WhoAmI Function Invoke-RestMethod -Uri ($baseURI + 'WhoAmI') -Method Get -Headers $baseHeaders | ConvertTo-Json
. $PSScriptRoot\Core.ps1
oben in der Datei zeigt die Verwendung von Dot-Sourcing an, um das Skript anzuweisen, den Inhalt dieser Datei zu laden.Denken Sie daran, den
https://yourorg.crm.dynamics.com/
-Wert so zu ändern, dass er mit der URL für Ihre Umgebung übereinstimmt.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sollte in etwa so 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
.Bearbeiten Sie die
test.ps1
-Datei und ändern Sie den Inhalt so, dass er wie im folgenden Skript aussieht:. $PSScriptRoot\Core.ps1 . $PSScriptRoot\CommonFunctions.ps1 Connect 'https://yourorg.crm.dynamics.com/' # change this # 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.Drücken Sie F5, um das Skript auszuführen.
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 this # 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.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sollte in etwa so 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 aber anfangen, Ihre eigenen Funktionen zu schreiben und zu verwenden, werden Sie auf Fehler stoßen. Diese Fehler stammen dann möglicherweise von Dataverse oder von Ihrem Skript.
Fügen wir eine Hilfsfunktion hinzu, die dabei helfen kann, die Fehlerquelle zu erkennen und relevante Details aus den von Dataverse zurückgegebenen Fehlern zu extrahieren.
Bearbeiten Sie die
Core.ps1
-Datei, um ihr die folgendeInvoke-DataverseCommands
-Funktion hinzuzufügen: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 zu verwenden, das einen ungültigensetName
-Parameterwert verwendet.account
sollteaccounts
sein. Dies ist ein häufiger Fehler. $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.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sollte in etwa so 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' }
Drücken Sie F5, um das Skript auszuführen.
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 Clientanwendungen über die Web-API außergewöhnliche Anforderungen an Serverressourcen stellen, gibt Dataverse 429 zu viele Anforderungen-Fehler zurück und die Clientanwendung muss den Vorgang für die in Retry-After-Header angegebene Zeit 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. Von Ihnen geschriebene Skripte können zum Senden der großen Anzahl von Anforderungen verwendet werden, die zum Auftreten dieser Fehler erforderlich sind. Sie sollten daher wissen, dass sie auftreten können und wie Sie sie 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
-Hashtable-Objekt als obligatorischen Parameter und eine boolesche returnHeader
-Kennzeichnung, um anzugeben, ob der Antwortheader 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, und es wird Out-Null verwendet, sodass die Ausgabe, die den leeren Antworttext darstellt, nicht mit der Funktion zurückgegeben wird. Andernfalls sendet die Funktion die Anforderung mit Invoke-RestMethod
mithilfe des request
-Objekts und gibt den Antworttext zurück.
Wenn Invoke-RestMethod
mit einem 429-Fehler fehlschlägt, wird geprüft, ob das request
-Objekt eine MaximumRetryCount
-Eigenschaft hat. Wenn nicht, wird eine mit dem Wert 3 hinzugefügt. Anschließend wird Invoke-RestMethod
unter Verwendung des Anforderungsobjekts und des Retry-After
-Antwortheader-Werts erneut versucht. 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 solche 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-Anforderungen und -Antworten, die mit dem Invoke-RestMethod-Cmdlet gesendet werden, nicht sichtbar, wenn Fiddler verwendet wird.
Um den HTTP-Datenverkehr mit 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
. Ihrer 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 ausgeführt wird, erhalten Sie eine Fehlermeldung wie diese:
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 sich dafür entscheiden, alle Ihre Invoke-RestMethod
-Aufrufe über eine einzige Funktion weiterzuleiten, wie zum Beispiel die Invoke-ResilientRestMethod
, die unter Dataverse-Dienstschutzgrenzwerte verwalten beschrieben ist, können Sie einige Variablen in der Core.ps1
-Datei festlegen, um diese Option an einem einzigen Ort zu konfigurieren.
# <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'
Anschließend können Sie in Ihrer zentralisierten Funktion den -Proxy
-Parameter durch Splatting mit der $request
-Hashtabelle nur beim Debuggen mit Fiddler festlegen.
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 CSDL $metadata sind die Quelle der Wahrheit über 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 this
$writeFileTo = 'C:\temp\yourorg.xml' # change this
## <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 CSDL-$metadata-Dokument für die Dataverse-Web-API wird im Visual Studio Code geöffnet.
Sie erhalten wahrscheinlich eine Benachrichtigung mit der Meldung:
Aus Leistungsgründen wurden Dokumentsymbole auf 5.000 Elemente begrenzt. Wenn ein neuer Grenzwert festgelegt wird, schließen Sie bitte diese Datei und öffnen Sie sie erneut, um die Dokumentsymbole neu zu berechnen.
Die Benachrichtigung bietet die Möglichkeit, den xml.symbols.maxItemsComputed
-Grenzwert der Visual Studio-XML-Erweiterung zu ändern. Für die meisten CSDL-$metadata-Dokumente der Dataverse-Web-API sollte es ausreichen, den Grenzwert auf 500.000 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 manchmal beim Debuggen mit Visual Studio Code auftreten. Beheben Sie diesen wie folgt:
- 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.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Tickets als Feedbackmechanismus für Inhalte auslaufen lassen und es durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unter:Einreichen und Feedback anzeigen für