当我在 Powershell 中执行 DevOps API 请求以检索工作项及其关系时,我有一个奇怪的行为。 我发现了很多其他帖子谈论这个,但我没有找到我的场景。
一些代码可以让您了解我在做什么。
这是我用于 API 调用的 Invoke-WebRequest 的包装器:
Function New-WebRequest {
[CmdletBinding()]
Param (
[ValidateNotNullOrEmpty()]
[ValidateSet("GET", "POST")]
[string] $Method = "GET",
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ApiCall,
[ValidateNotNullOrEmpty()]
[string] $RequestBody,
[ValidateNotNullOrEmpty()]
[string] $RequestContentType = "application/json"
)
if($ApiCall -notmatch $REGEX_URL) {
Write-Error "The provided URL ($ApiCall) is not in the correct format"
Exit 1
}
try
{
Write-Debug "API Request Call: [$ApiCall]"
$Command = "Invoke-WebRequest
-Method $Method
-Uri `"$ApiCall`"
-UseBasicParsing
-Headers @{Authorization = `"Basic $ENCODED_PAT`"}
-ContentType $RequestContentType"
if($PSBoundParameters.ContainsKey("RequestBody") -and -not([string]::IsNullOrWhiteSpace($RequestBody))) {
Write-Debug "API Request Body: [$RequestBody]"
$Command += " -Body '$RequestBody'"
}
$Exec = [ScriptBlock]::Create($Command -Replace "\r\n")
$Response = & $Exec
$StatusCode = $Response.StatusCode
}
catch {
$StatusCode = $_.Exception.Response.StatusCode.value__
Write-Error "Error Occured: $_"
}
if ($StatusCode -eq 200) {
$ResponseBody = $Response.Content | ConvertFrom-Json
} else {
throw "API Call failed (Status code: $StatusCode)"
}
return $ResponseBody
}
这是我用来检索工作项的方法:
Function Get-WorkItem {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true, Position=0)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("\d{5,6}")]
[string] $Id,
[ValidateSet("All", "None", "Fields", "Links", "Relations")]
[string] $Expand = "All",
[string[]] $Fields,
[switch] $IncludeUpdates
)
Write-Debug "Retrieving Work Item [$Id]..."
$ApiCall = "$API_BASE_URL/wit/workitems/$($Id)?"
$Params = @("`$expand=$Expand")
if($PSBoundParameters.ContainsKey("Fields")) {
if($Expand -ne "None" -or $Expand -ne "Links" ) {
Write-Error "The 'Fields' parameter can be used only if 'Expand' is 'None' or 'Links' as per API definition"
} else {
$Params += "fields=$($Fields -Join ",")"
}
}
$ApiCall = Add-APIPart -URL $ApiCall -Params $Params
$Body = New-WebRequest -ApiCall $ApiCall
if($PSBoundParameters.ContainsKey("IncludeUpdates")) {
$Call = "$API_BASE_URL/wit/workitems/$Id/updates"
$Updates = (New-WebRequest -ApiCall $Call).Value
}
return (?: { $null -eq $Updates } `
{ $Body } `
{ @{
Body = $Body;
Updates = $Updates;
} }
)
}
如您所见,“$expand”参数默认为“All”(即使我也尝试过“Relations”)。
问题是,在 Powershell 中打印响应时,我根本没有“关系”字段:
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
fields NoteProperty System.Management.Automation.PSCustomObject fields=@{System.AreaPath=....; System.TeamProject=....; System.IterationPath=....
id NoteProperty int id=135215
rev NoteProperty int rev=39
url NoteProperty string url=https://dev.azure.com/nestle-globe/......./_apis/wit/workItems/135215
_links NoteProperty System.Management.Automation.PSCustomObject _links=@{self=; workItemUpdates=; workItemRevisions=; workItemComments=; html=; workItemType=; fields=}
但是如果我在浏览器中打开链接,我可以看到它:
这是我传递给网络请求的内容:
DEBUG: Retrieving Work Item [135215]... DEBUG: API Request Call: [https://dev.azure.com/......./......../_apis/wit/workitems/135215?$expand=All&api-version=7.0]
我尝试将不同的值传递给 REST API 的“$expand”参数,但没有任何区别。 我还尝试删除 Invoke-WebRequest 中的“-UseBasicParsing”开关,但它没有改变任何东西。
从响应中,它有以下API请求调用:
https://dev.azure.com/......./......../_apis/wit/workitems/135215?$expand=All&api-version=7.0
尝试直接放到
Invoke-WebRequest
方法中,会报错如下:
$
中的$expand
导致了错误。可以使用以下格式来修复:
+
组合:$ApiCall = "https://dev.azure.com/{org}/{project}/_apis/wit/workitems/33223?$" + "expand=All&api-version=7.0"
%24
代替 $
: $ApiCall = "https://dev.azure.com/wadez0770/wadetest1/_apis/wit/workitems/33223?%24expand=All&api-version=7.0"
此外,对于
Invoke-WebRequest
响应,您需要解析json响应:
$response = Invoke-WebRequest -Method GET -Uri $ApiCall -Headers $headers -ContentType $RequestContentType
# Parse the JSON response
$jsonResponse = $response.Content | ConvertFrom-Json
# Access the relations
$relations = $jsonResponse.relations
# Output the relations
$relations
关系返回: