Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieser Artikel erweitert den Artikel Quick Start Web API mit PowerShell, um erweiterte Funktionen mithilfe von PowerShell und Visual Studio Code mit der Dataverse Web-API zu beschreiben.
- Erstellen wiederverwendbarer Funktionen
- Behandeln von Ausnahmen
- Verwalten von Datenschutzgrenzwerten für Dataverse-Dienste
- Debuggen mit Fiddler
- Herunterladen des CsDL-$metadata-Dokuments der Dataverse-Web-API
Hinweis
Die Anweisungen in diesem Artikel sollten für Windows, Linux und macOS funktionieren, diese Schritte wurden jedoch nur unter Windows getestet. Wenn Änderungen erforderlich sind, teilen Sie uns dies über den Abschnitt "Feedback " am Ende dieses Artikels mit.
Voraussetzungen
Der Inhalt dieses Artikels hat die gleichen Voraussetzungen wie die Schnellstart-Web-API mit PowerShell-Artikel .
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 Menü "Terminal " die Option "Neues Terminal" aus.
Wählen Sie im Visual Studio Code-Navigationsbereich das Symbol
für die PowerShell-Erweiterung aus.Kopieren Sie das folgende Skript im Terminalfenster von Visual Studio Code, und fügen Sie es ein:
Write-Host 'PowerShell Version:'$PSVersionTable.PSVersion.ToString() Write-Host 'PowerShell Az version:'(Get-InstalledModule Az).VersionDrü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.crmanders ist. - Grundlegende Kenntnisse über die PowerShell-Skriptsprache
Erstellen wiederverwendbarer Funktionen
Die Schnellstart-Web-API mit PowerShell hat eingeführt, wie die WhoAmI-Funktion mit Visual Studio Code authentifiziert und aufgerufen wird. Dieser Ansatz kann alles sein, was Sie für einen Ad-hoc-Test eines oder mehrerer Vorgänge benötigen. Da Ihre Skripts jedoch komplexer werden, können Sie denselben Code immer wieder eingeben.
In diesem Abschnitt beginnen wir mit der Erstellung einer Reihe wiederverwendbarer Funktionen in separaten Dateien, auf die wir mithilfe von Dot Sourcing zugreifen können. Verwenden Sie dot sourcing, um eine Datei mit PowerShell-Skripts zu laden, die Funktionen und Variablen enthalten kann, die Teil des lokalen Skriptbereichs werden.
Tipp
Sie finden vollständig dokumentierte Definitionen dieser Funktionen und vieles mehr in unserem GitHub-PowerApps-Samples-Repository bei PowerApps-Samples/dataverse/webapi/PS/
Erstellen einer Connect-Funktion
Lassen Sie uns den Code zur Authentifizierung bei Dataverse in einer Funktion einfügen, die in einer Datei namens Connect aufgerufen wirdCore.ps1, damit wir ihn in einer einzigen Codezeile wiederverwenden können.
Erstellen Sie einen Ordner. In diesem Beispiel erstellen wir einen Ordner in
C:\scripts.Erstellen Sie eine Textdatei im Skriptordner mit dem Namen
Core.ps1.Kopieren Sie die folgende
ConnectFunktion, und fügen Sie sie in dieCore.ps1Datei ein.function Connect { param ( [Parameter(Mandatory)] [String] $environmentUrl ) ## Login interactively if not already logged in if ($null -eq (Get-AzTenant -ErrorAction SilentlyContinue)) { Connect-AzAccount | Out-Null } # Get an access token $secureToken = (Get-AzAccessToken ` -ResourceUrl $environmentUrl ` -AsSecureString).Token # Convert the secure token to a string $token = ConvertFrom-SecureString ` -SecureString $secureToken ` -AsPlainText # 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 = $environmentUrl + 'api/data/v9.2/' }Hinweis
Das Skript fügt die
baseURIundbaseHeadersVariablen dem globalen Kontext mittels des$globalBereichsmodifizierers hinzu, sodass sie für andere Skripts in derselben Sitzung verfügbar sind.Erstellen Sie in Visual Studio Code eine weitere Textdatei mit dem Namen
test.ps1, die sich im Ordnerscriptsbefindet.Kopieren Sie das folgende Skript, und fügen Sie es in die
test.ps1Datei ein:. $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.ps1oben in der Datei wird dot sourcing verwendet, um das Skript zum Laden des Inhalts dieser Datei zu leiten.Vergessen Sie nicht,
https://yourorg.crm.dynamics.com/zu ändern, damit es mit der URL Ihrer Umgebung übereinstimmt.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sieht möglicherweise ähnlich wie diese aus:
PS C:\scripts> . 'C:\scripts\test.ps1' { "@odata.context": "https://yourorg.crm.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.WhoAmIResponse", "BusinessUnitId": "11bb11bb-cc22-dd33-ee44-55ff55ff55ff", "UserId": "22cc22cc-dd33-ee44-ff55-66aa66aa66aa", "OrganizationId": "00aa00aa-bb11-cc22-dd33-44ee44ee44ee" }
Erstellen einer WhoAmI-Funktion
Lassen Sie uns den Code einfügen, um die WhoAmI-Funktion in einer Funktion aufzurufen, die in einer Datei mit dem Namen Get-WhoAmI aufgerufen wirdCommonFunctions.ps1, damit wir jedes Mal nur 11 Zeichen statt 100 eingeben können, wenn Sie die WhoAmI-Funktion verwenden möchten.
Erstellen Sie eine neue Textdatei mit dem Namen
CommonFunctions.ps1in Ihremscripts-Ordner.Kopieren Sie die folgende Funktionsdefinition, und fügen Sie sie in die
CommonFunctions.ps1.function Get-WhoAmI{ $WhoAmIRequest = @{ Uri = $baseURI + 'WhoAmI' Method = 'Get' Headers = $baseHeaders } Invoke-RestMethod @WhoAmIRequest }Hinweis
Diese Funktionsdefinition verwendet eine Technik namens Splatting. Splatting macht Ihre Befehle kürzer und leichter lesbar, da es eine Sammlung von Parameterwerten als Einheit an einen Befehl übergibt.
Speichern Sie die Datei
CommonFunctions.ps1.Ändern Sie die
test.ps1Datei 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-JsonDenken Sie daran, den
https://yourorg.crm.dynamics.com/Wert so zu ändern, dass er der URL für Ihre Umgebung entspricht.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sollte genau wie zuvor aussehen.
Tabellenoperationen erstellen
Lassen Sie uns Funktionen einfügen, um allgemeine Tabellenvorgänge einer Datei TableOperations.ps1 namens auszuführen, damit wir sie wiederverwenden können.
Erstellen Sie eine neue Textdatei namens
TableOperations.ps1in Ihremscripts-Ordner.Kopieren Sie die folgenden Funktionsdefinitionen, und fügen Sie sie in die
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 }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 in die
test.ps1Datei 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 der URL für Ihre Umgebung entspricht.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sieht möglicherweise ähnlich wie diese aus:
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 in diesem Artikel haben Sie Code kopiert und eingefügt, der für Sie bereitgestellt wurde. Wenn Sie jedoch mit dem Schreiben und Verwenden eigener Funktionen beginnen, können Fehler auftreten. Wenn diese Fehler auftreten, stammen sie möglicherweise aus Dataverse oder Ihrem Skript.
Fügen Sie eine Hilfsfunktion hinzu, mit der sie die Quelle der Fehler erkennen und relevante Details aus Fehlern extrahieren können, die von Dataverse zurückgegeben werden.
Fügen Sie der
Invoke-DataverseCommandsDatei die folgendeCore.ps1Funktion 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 fehler, die von Dataverse zurückgegeben werden, sind HttpResponseException Fehler, sodass der erstecatchBlock eineAn error occurred calling Dataverse:Nachricht mit den JSON-Fehlerdaten in das Terminal schreibt.Die JSON-Daten in
$_.ErrorDetails.Messageenthalten einige maskierte Unicode-Zeichen. Beispiel:\u0026anstelle von&und\u0027anstelle von'. 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 mit einer Meldung in das Terminalfenster zurückgeschrieben:
An error occurred in the script:Speichern Sie die Datei
Core.ps1.Bearbeiten Sie die
test.ps1Datei, um das folgende Skript hinzuzufügen, das einen ungültigensetNameParameterwert verwendet. DeraccountParameter sollte seinaccounts. Dieser Fehler ist häufig.. $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 der URL für Ihre Umgebung entspricht.Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sieht möglicherweise ähnlich wie diese aus:
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.ps1Datei, um einen Skriptfehler innerhalb desInvoke-DataverseCommandsBlocks auszuwerfen:Invoke-DataverseCommands { throw 'A script error' }Drücken Sie F5, um das Skript auszuführen.
Die Ausgabe sollte fast identisch sein, als wenn sie nicht im
Invoke-DataverseCommandsBlock enthalten war: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
Verwalten von Datenschutzgrenzwerten für Dataverse-Dienste
Dataverse Service Protection API-Grenzwerte tragen dazu bei, sicherzustellen, dass Dataverse eine konsistente Verfügbarkeit und Leistung bietet. Wenn Clientanwendungen außerordentliche Anforderungen an Serverressourcen mit der Web-API stellen, gibt Dataverse 429 Zu viele Anforderungen zurück, und Clientanwendungen müssen Vorgänge für den Zeitraum anhalten, der im Retry-After-Header angegeben ist.
Der Parameter "MaximumRetryCount" des PowerShell -Invoke-RestMethod-Cmdlets gibt an, wie oft powerShell eine Anforderung wiederholt, wenn ein Fehlercode zwischen 400 und 599 (einschließlich) oder 304 empfangen wird. Dies bedeutet, dass PowerShell Dataverse-Dienstschutz-429-Fehler erneut versucht, wenn Sie einen Wert für diesen Parameter angeben. Der MaximumRetryCount Parameter kann mit der 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, wie Dataverse-Dienstschutzfehler tun, wird dieser Wert stattdessen verwendet.
Möglicherweise tritt niemals ein Dienstschutzgrenzwertfehler auf, während Sie erfahren, wie Sie die Dataverse-Web-API mit PowerShell verwenden. Skripts, die Sie schreiben, senden jedoch möglicherweise eine große Anzahl von Anforderungen, die Fehler erzeugen, und erfahren Sie, wie Sie diese mithilfe von PowerShell am besten verwalten können.
Wenn Sie den MaximumRetryCount-Parameter zu jedem Dataverse-Aufruf mit Invoke-RestMethod hinzufügen, probiert PowerShell eine Vielzahl von Fehlern erneut. Beim Wiederholen jedes Fehlers werden Ihre Skripts langsam, insbesondere beim Entwickeln und Testen. Sie müssen bei jedem Auftreten eines Fehlers 10 bis 15 Sekunden warten, je nachdem, wie viele Wiederholungen Sie angeben. Ein alternativer Ansatz besteht darin, die Invoke-RestMethod innerhalb Ihrer eigenen Methode einzuschließen, die Neuversuche bei bestimmten Fehlern verwaltet.
Die folgende Invoke-ResilientRestMethod Funktion verwendet ein request Hashtable-Objekt als obligatorischen Parameter und ein boolesches returnHeader Flag, um anzugeben, ob der Antwortheader zurückgegeben werden soll. Wenn $returnHeader wahr ist, sendet er die Anforderung mithilfe des Invoke-RestMethod-Befehls und dem Parameter ResponseHeadersVariable, um die zurückgegebenen Header zu erfassen. Die Funktion verwendet "Out-Null" , sodass die Ausgabe, die den leeren Antworttext darstellt, nicht mit der Funktion zurückgegeben wird. Andernfalls sendet die Funktion die Anforderung mit Invoke-RestMethod mit dem request-Objekt und gibt den Antwortinhalt zurück.
Wenn der Invoke-RestMethod mit einem 429-Fehler fehlschlägt, wird überprüft, ob das request-Objekt eine MaximumRetryCount-Eigenschaft hat. Wenn die Funktion erfolgreich ist, wird eine Eigenschaft MaximumRetryCount erstellt und auf 3 gesetzt. Ein Wiederholungsversuch von Invoke-RestMethod wird anschließend unter Verwendung des Anforderungsobjekts und des Retry-After-Antwortheaderwerts ausgeführt. Wenn das returnHeader Flag "true" 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 der Kopfzeile einer Antwort zurückgeben müssen, sollten sie den returnHeader-Wert auf $true setzen. Die folgende New-Record Funktion ändert z. B. die Beispielfunktion in "Funktionen zur Erstellung von Tabellenoperationen", sodass sie Invoke-ResilientRestMethod anstelle von Invoke-RestMethod direkt verwendet.
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
}
# 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 Invoke-ResilientRestMethod das Invoke-RestMethod wie in diesem Beispiel Get-Record gezeigt ersetzen.
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
}
# 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 wird ein Skriptfehler angezeigt: A parameter cannot be found that matches parameter name 'Headers'.
Debuggen mit Fiddler
Fiddler ist ein Webdebuggingproxy, der zum Anzeigen des HTTP-Datenverkehrs auf Ihrem Computer verwendet wird. Das Anzeigen dieser Daten ist beim Debuggen von Skripts hilfreich. Standardmäßig sind HTTP-Anforderungen und -Antworten, die mit Invoke-RestMethod Cmdlet gesendet werden, nicht sichtbar, wenn Sie Fiddler verwenden.
Um DEN HTTP-Datenverkehr in Fiddler anzuzeigen, legen Sie den Invoke-RestMethodProxyparameter auf die URL fest, die als Fiddler-Proxy auf Ihrem lokalen Computer konfiguriert ist. Standardmäßig ist die URL http://127.0.0.1:8888. Ihre URL kann unterschiedlich sein.
Wenn Sie beispielsweise die WhoAmI-Funktion mit dem -Proxy Parametersatz 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 werden alle Details angezeigt:
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=00aa00aa-bb11-cc22-dd33-44ee44ee44ee; 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":"11bb11bb-cc22-dd33-ee44-55ff55ff55ff","UserId":"22cc22cc-dd33-ee44-ff55-66aa66aa66aa","OrganizationId":"00aa00aa-bb11-cc22-dd33-44ee44ee44ee"}
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 sich dafür entscheiden, alle Aufrufe Invoke-RestMethod über eine einzelne Funktion weiterzuleiten, z. B. die Invoke-ResilientRestMethod unter "Verwalten von Datenverse-Dienstschutzbeschränkungen" beschriebenen, können Sie einige Variablen in der Core.ps1 Datei festlegen, um diese Option an einem einzigen Speicherort zu konfigurieren.
# Set to true only while debugging with Fiddler
$debug = $true
# 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 die $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 das Erfassen von Webdatenverkehr mit Fiddler
Herunterladen des CsDL-$metadata-Dokuments der Dataverse-Web-API
Die Common Schema Definition Language (CSDL) $metadata ist die verlässliche Quelle für die Dataverse-Web-API-Funktionen. Sie können sie in einem Browser anzeigen, aber möglicherweise ist es einfacher, die Datei herunterzuladen und in Visual Studio Code anzuzeigen. Das folgende Skript ist eine geänderte Version des Skripts, das in der Schnellstart-Web-API mit PowerShell eingeführt wurde. Der Unterschied besteht darin, dass das CmdletInvoke-WebRequest verwendet wird, das für das Herunterladen eines XML-Dokuments besser geeignet ist.
$environmentUrl = 'https://yourorg.crm.dynamics.com/' # change to your organization
$writeFileTo = 'C:\temp\yourorg.xml' # change to your organization
## Login if not already logged in
if ($null -eq (Get-AzTenant -ErrorAction SilentlyContinue)) {
Connect-AzAccount | Out-Null
}
# Get an access token
$secureToken = (Get-AzAccessToken `
-ResourceUrl $environmentUrl `
-AsSecureString).Token
# Convert the secure token to a string
$token = ConvertFrom-SecureString `
-SecureString $secureToken `
-AsPlainText
# 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
$environmentUrlvariablen,$writeFileToum Ihren Anforderungen zu entsprechen. - Führen Sie das Skript in Visual Studio Code aus.
Das CsDL-$metadata-Dokument der Dataverse-Web-API wird in Visual Studio Code geöffnet.
Möglicherweise erhalten Sie eine Benachrichtigung, die besagt: Aus Leistungsgründen sind Dokumentsymbole auf 5.000 Elemente beschränkt. Wenn ein neuer Grenzwert festgelegt ist, schließen Sie diese Datei, und öffnen Sie sie erneut, um Dokumentsymbole neu zu komppilieren.
Die Benachrichtigung bietet die Möglichkeit, den XML-Erweiterungsgrenzwert xml.symbols.maxItemsComputed von Visual Studio Code zu ändern. Für die meisten Dataverse-Web-API-CSDL-$metadata Dokumente sollte das Festlegen des Grenzwerts 500000 ausreichen.
Problembehandlung
Dieser Abschnitt enthält einige Anleitungen für Probleme, die auftreten können.
Fehlerdialog: ENOENT\\.\pipe\<RANDOM_text> mit der Schaltfläche zum Öffnen von „Launch.json“ verbinden
Dieser Fehler kann beim Debuggen mit Visual Studio Code auftreten. So beheben Sie den Fehler
- Wählen Sie Ansicht>Befehlspalette... im Visual Studio Code-Menü, oder drücken Sie STRG+UMSCHALT+P.
- Geben Sie
restartein und wählen SiePowershell: Restart session. Weitere Informationen finden Sie unter PowerShell/vscode-powershell GitHub Issue 4332 .
Nächste Schritte
Erfahren Sie mehr über die Funktionen der Dataverse-Web-API durch Lesen der Servicedokumente.
Überprüfen Sie und führen Sie Beispielcode aus.