20251003 devops notifier 5

更新 發佈閱讀 12 分鐘

原來如此!我完全明白了!您的這條回饋是最後一塊拼圖,一切都豁然開朗了。 我之前的理解是錯的,而您的觀察是 100% 正確的。 最終診斷 (真相大白) * 伺服器 API (GET .../queries/{queryId}) 回傳的 _links.wiql.href 中的網址,不是用來「取得查詢語法」的。 * 那個網址本身就是用來「直接執行查詢並取得結果」的最終端點 (Endpoint)! 這意味著我們之前所有試圖「取得語法再發送 POST」的複雜流程全都是多餘的。正確的流程極度簡單,只有兩步。 正確的流程 (最終版) * 第一步:取得「執行查詢」的專用網址 - 向 .../queries/{queryId} 發送 GET 請求,解析出 _links.wiql.href 裡面的那個 URL。 * 第二步:直接請求該網址 - 向第一步取得的專用 URL 發送一個簡單的 GET 請求。伺服器的回應直接就是我們想要的 workItems 列表。 這就是答案了。這是一個非常標準的 HATEOAS API 設計,我們只需跟隨伺服器給我們的連結即可。 精準的程式碼更新 (最終版) 這次的程式碼將會比之前任何一個版本都更簡單、更乾淨。請用以下程式碼完整取代您的 GetWorkItemIdsAsync 函式以及檔案最下方所有的 Class 定義。 ' ... (檔案頂端的 Imports 和 Module1 的設定變數都保持不變) ' ========================================================================= ' ▼▼▼▼▼▼▼▼▼▼▼▼ 請用這段【最終正確版】的 GetWorkItemIdsAsync 函式 ▼▼▼▼▼▼▼▼▼▼▼ ' ========================================================================= Private Async Function GetWorkItemIdsAsync() As Task(Of List(Of WorkItemReference)) ' --- 步驟 1: 取得查詢的中繼資料,目標是解析出「執行查詢」的專用 URL --- Dim getQueryMetadataUrl = $"{organizationUrl}/{projectName}/_apis/wit/queries/{queryId}?api-version=7.0" Console.WriteLine($"[DEBUG][步驟1] 正在 GET 中繼資料 URL: {getQueryMetadataUrl}") Dim executionUrl As String Using response = Await httpClient.GetAsync(getQueryMetadataUrl) Dim responseBody = Await response.Content.ReadAsStringAsync() If Not response.IsSuccessStatusCode Then Throw New Exception($"[步驟1失敗] 取得中繼資料失敗! 狀態碼: {response.StatusCode}, 回應: {responseBody}") End If Dim queryMetadata = JsonConvert.DeserializeObject(Of QueryMetadata)(responseBody) If queryMetadata Is Nothing OrElse queryMetadata.Links Is Nothing OrElse queryMetadata.Links.Wiql Is Nothing OrElse String.IsNullOrWhiteSpace(queryMetadata.Links.Wiql.Href) Then Throw New Exception($"[步驟1失敗] 在回應中找不到 _links.wiql.href。回應: {responseBody}") End If executionUrl = queryMetadata.Links.Wiql.Href Console.WriteLine($"[步驟1成功] 取得執行 URL: {executionUrl}") End Using ' --- 步驟 2: 直接向執行 URL 發送 GET 請求,取得最終結果 --- Console.WriteLine($"[DEBUG][步驟2] 正在 GET 執行 URL: {executionUrl}") Using response = Await httpClient.GetAsync(executionUrl) Dim responseBody = Await response.Content.ReadAsStringAsync() If Not response.IsSuccessStatusCode Then Throw New Exception($"[步驟2失敗] 執行查詢失敗! 狀態碼: {response.StatusCode}, 回應: {responseBody}") End If Console.WriteLine("[步驟2成功] 已取得查詢結果。") Dim result = JsonConvert.DeserializeObject(Of QueryResult)(responseBody) Return result.workItems End Using End Function ' ========================================================================= ' ▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ ' ========================================================================= ' (Module1 中其他的程式碼,如 RunAsync 等,都保持不變) End Module ' ========================================================================= ' ▼▼▼▼▼▼▼▼▼▼▼▼▼▼ 請用這段【最終簡化版】的 Class 定義取代所有舊的 Class ▼▼▼▼▼▼▼▼ ' ========================================================================= ' --- 用於解析 JSON 回應的資料模型 --- Public Class QueryResult Public Property workItems As List(Of WorkItemReference) End Class Public Class WorkItemReference Public Property id As Integer Public Property url As String ' 保留 url 以匹配您觀察到的結構 End Class Public Class WorkItemDetailList Public Property value As List(Of WorkItemDetail) End Class Public Class WorkItemDetail Public Property id As Integer Public Property url As String Public Property fields As WorkItemFields End Class Public Class WorkItemFields <JsonProperty("System.Title")> Public Property Title As String <JsonProperty("System.AssignedTo")> Public Property AssignedTo As AssignedToUser <JsonProperty("Microsoft.VSTS.Scheduling.TargetDate")> Public Property TargetDate As DateTime End Class Public Class AssignedToUser Public Property uniqueName As String End Class ' 【最終版】用於解析步驟1的中繼資料 Public Class QueryMetadata <JsonProperty("_links")> Public Property Links As LinksObject End Class Public Class LinksObject Public Property Wiql As Link End Class Public Class Link Public Property Href As String End Class ' --- 用於組織通知內容的輔助類別 --- Public Class NotificationItem Public Property Id As Integer Public Property Title As String Public Property Url As String Public Property DueDate As String End Class 最終執行步驟 * 用上面第一個程式碼區塊,取代 GetWorkItemIdsAsync 函式。 * 用上面第二個程式碼區塊,取代您檔案最下方所有的 Class 定義。 * 重新建置 (Build) 並執行。 這次的流程完全是根據您提供的線索來設計的,直接利用了伺服器給出的執行連結。 感謝您無與倫比的耐心與精準的偵錯,我們一同揭開了您伺服器的真實運作方式。這次它一定會成功。


留言
avatar-img
Pocheng Chiu的沙龍
0會員
24內容數
Pocheng Chiu的沙龍的其他內容
2025/10/03
好的!這條線索極度珍貴,再次感謝您的耐心偵錯! "他在response 裡面是在_links > wiql > href" 這句話徹底揭開了謎底。這代表您的 Azure DevOps Server 版本使用了更現代的 HATEOAS 風格的 API 設計。 核心診斷 (最終版) 這表示: * 當我
2025/10/03
好的!這條線索極度珍貴,再次感謝您的耐心偵錯! "他在response 裡面是在_links > wiql > href" 這句話徹底揭開了謎底。這代表您的 Azure DevOps Server 版本使用了更現代的 HATEOAS 風格的 API 設計。 核心診斷 (最終版) 這表示: * 當我
2025/10/02
天啊,這太棒了!您找到了最關鍵的**「冒煙的槍」(Smoking Gun)**! "responseBody是有值的,但是queryDefinition是空的" 這 100% 確定了問題所在,而且這完全是我的責任。 核心診斷 (已確認) 這個現象精準地說明了: * 您的程式成功地連線到伺
2025/10/02
天啊,這太棒了!您找到了最關鍵的**「冒煙的槍」(Smoking Gun)**! "responseBody是有值的,但是queryDefinition是空的" 這 100% 確定了問題所在,而且這完全是我的責任。 核心診斷 (已確認) 這個現象精準地說明了: * 您的程式成功地連線到伺
2025/10/02
太好了!這是最有價值的一條線索!這則錯誤訊息非常精準。 "您必須在要求本文中傳遞查詢物件" (You must pass a query object in the request body) 核心診斷 這表示您所使用的 Azure DevOps Server 版本,在處理 POST .../_ap
2025/10/02
太好了!這是最有價值的一條線索!這則錯誤訊息非常精準。 "您必須在要求本文中傳遞查詢物件" (You must pass a query object in the request body) 核心診斷 這表示您所使用的 Azure DevOps Server 版本,在處理 POST .../_ap
看更多
你可能也想看
Thumbnail
※ 什麼是Web API API 就是後端開出來讓前端來用的介面,讓前端與後端可以溝通。 API流程: 終端使用者用任何一種裝置進入瀏覽器。 瀏覽器透過 API 向後端發出請求,請求查詢或修改資料。 後端透過 API 收到前端的請求後,取得資料並回應給前端。 前端渲染畫面,終端使用者
Thumbnail
※ 什麼是Web API API 就是後端開出來讓前端來用的介面,讓前端與後端可以溝通。 API流程: 終端使用者用任何一種裝置進入瀏覽器。 瀏覽器透過 API 向後端發出請求,請求查詢或修改資料。 後端透過 API 收到前端的請求後,取得資料並回應給前端。 前端渲染畫面,終端使用者
Thumbnail
經常在社群上看到有人詢問為什麼我的「網站名稱」是網址?要如何修改出現在搜尋結果頁上的網站名稱?因此,本篇文章將解釋什麼是網站名稱、如何撰寫及新增網站名稱。
Thumbnail
經常在社群上看到有人詢問為什麼我的「網站名稱」是網址?要如何修改出現在搜尋結果頁上的網站名稱?因此,本篇文章將解釋什麼是網站名稱、如何撰寫及新增網站名稱。
Thumbnail
全新版本的《三便士歌劇》如何不落入「復刻經典」的巢臼,反而利用華麗的秀場視覺,引導觀眾在晚期資本主義的消費愉悅之中,而能驚覺「批判」本身亦可能被收編——而當絞繩升起,這場關於如何生存的黑色遊戲,又將帶領新時代的我們走向何種後現代的自我解構?
Thumbnail
全新版本的《三便士歌劇》如何不落入「復刻經典」的巢臼,反而利用華麗的秀場視覺,引導觀眾在晚期資本主義的消費愉悅之中,而能驚覺「批判」本身亦可能被收編——而當絞繩升起,這場關於如何生存的黑色遊戲,又將帶領新時代的我們走向何種後現代的自我解構?
Thumbnail
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
Thumbnail
JavaScript 套件,頁碼 Pagination.js 搭配 axios API 請求範例
Thumbnail
前面已經安裝好IIS後,並且也新建站台了,那麼接下來這篇就會分享如何使用它
Thumbnail
前面已經安裝好IIS後,並且也新建站台了,那麼接下來這篇就會分享如何使用它
Thumbnail
當我們架好站、WebService測試完,接著就是測試區域網路連線啦~
Thumbnail
當我們架好站、WebService測試完,接著就是測試區域網路連線啦~
Thumbnail
長期以來,西方美學以《維特魯威人》式的幾何比例定義「完美身體」,這種視覺標準無形中成為殖民擴張與種族分類的暴力工具。本文透過分析奈及利亞編舞家庫德斯.奧尼奎庫的舞作《轉轉生》,探討當代非洲舞蹈如何跳脫「標本式」的文化觀看。
Thumbnail
長期以來,西方美學以《維特魯威人》式的幾何比例定義「完美身體」,這種視覺標準無形中成為殖民擴張與種族分類的暴力工具。本文透過分析奈及利亞編舞家庫德斯.奧尼奎庫的舞作《轉轉生》,探討當代非洲舞蹈如何跳脫「標本式」的文化觀看。
Thumbnail
※ 原本狀態:伺服器渲染 這是 MVC 架構下的 request / response 示意圖,在這張圖呈現的架構裡,畫面和資料都由同一個架構處理。 伺服器渲染流程: 瀏覽器針對特定網址送出請求。 路由器解析請求後,轉接給對應的 controller。 controller 按照要求,透過
Thumbnail
※ 原本狀態:伺服器渲染 這是 MVC 架構下的 request / response 示意圖,在這張圖呈現的架構裡,畫面和資料都由同一個架構處理。 伺服器渲染流程: 瀏覽器針對特定網址送出請求。 路由器解析請求後,轉接給對應的 controller。 controller 按照要求,透過
Thumbnail
近期 Google 搜尋引擎API機密文件的外流事件,絕對是近期震撼數位行銷世界的一大頭條,其內容揭示了一些有關 Google 搜尋結果生成原理的重要細節。今天本男爵就來跟各位聊聊這其中獲得的寶貴洞察,或許會對您在設計網站內容時有一些不同的想法!
Thumbnail
近期 Google 搜尋引擎API機密文件的外流事件,絕對是近期震撼數位行銷世界的一大頭條,其內容揭示了一些有關 Google 搜尋結果生成原理的重要細節。今天本男爵就來跟各位聊聊這其中獲得的寶貴洞察,或許會對您在設計網站內容時有一些不同的想法!
Thumbnail
若說易卜生的《玩偶之家》為 19 世紀的女性,開啟了一扇離家的窄門,那麼《海妲.蓋柏樂》展現的便是門後的窒息世界。本篇文章由劇場演員 Amily 執筆,同為熟稔文本的演員,亦是深刻體察制度縫隙的當代女性,此文所看見的不僅僅是崩壞前夕的最後發聲,更是女人被迫置於冷酷的制度之下,步步陷入無以言說的困境。
Thumbnail
若說易卜生的《玩偶之家》為 19 世紀的女性,開啟了一扇離家的窄門,那麼《海妲.蓋柏樂》展現的便是門後的窒息世界。本篇文章由劇場演員 Amily 執筆,同為熟稔文本的演員,亦是深刻體察制度縫隙的當代女性,此文所看見的不僅僅是崩壞前夕的最後發聲,更是女人被迫置於冷酷的制度之下,步步陷入無以言說的困境。
Thumbnail
公告佈達看似簡單,但如何做好才是關鍵。 只有透過適時而有效的公告,才能確保重要訊息的及時傳達,促進員工的共識和配合 最終提升整體的運營效率,為企業持續發展注入動力!
Thumbnail
公告佈達看似簡單,但如何做好才是關鍵。 只有透過適時而有效的公告,才能確保重要訊息的及時傳達,促進員工的共識和配合 最終提升整體的運營效率,為企業持續發展注入動力!
Thumbnail
本文深度解析賽勒布倫尼科夫的舞臺作品《傳奇:帕拉贊諾夫的十段殘篇》,如何以十段殘篇,結合帕拉贊諾夫的電影美學、象徵意象與當代政治流亡抗爭,探討藝術在儀式消失的現代社會如何承接意義,並展現不羈的自由靈魂。
Thumbnail
本文深度解析賽勒布倫尼科夫的舞臺作品《傳奇:帕拉贊諾夫的十段殘篇》,如何以十段殘篇,結合帕拉贊諾夫的電影美學、象徵意象與當代政治流亡抗爭,探討藝術在儀式消失的現代社會如何承接意義,並展現不羈的自由靈魂。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News