HttpClient.PatchAsJsonAsync - dotnet/runtime 專案貢獻小記

沈星繁發表於2021-10-26

TL;DR

迫於 PatchAsJsonAsync 方法缺失,我給 dotnet/runtime 專案貢獻了相關的 API,可惜要到 .NET7 才能用上。

https://github.com/dotnet/runtime/pull/60672

正文

同事小陳issue 收到了回覆,希望他可以提供一個標準的 API Proposal 以供後續 review 使用。坐在隔壁的我得知此事之後,主動接過了這個鍋([API Proposal]: HttpClient.PatchAsJsonAsync()),然後就有了這篇博文接下來的內容。

API Review 是線上直播的模式,有興趣的可以去看一下,還是挺好玩的,issue 裡有提到視訊的地址。

視訊裡有提到,這個 API 是從 json.net 相關的 API 遷移過來的,當時就沒有 PATCH 方法的過載。顯然 PATCH 方法沒什麼人用,這個 API 就慘遭 Overlooked(忽視) 了。

一個悲傷的故事,我的 Proposal 裡 API 是直接複製貼上然後替換的,裡面有個語法錯誤,Review 的人也是複製貼上的,幸好後來有人發現了(果然天下程式設計師都是一招 Ctrl + CV)。

接下來進行開發,其實也就是複製貼上的事 = =。

首先在 GitHub fork dotnet/runtime 儲存庫,再克隆到本地。

我平時主要使用 Rider,因此 VS 裡很多工作負載沒裝。在 VS Installer 裡勾上 .NET 桌面開發,Python 開發和 C++ 桌面開發,根據提示重啟電腦。

一定要記得 關閉 Resharper,不然之後開啟 VS 的時候就會這樣:

接下來根據官方給的步驟走就可以(https://github.com/dotnet/runtime/blob/main/docs/workflow/building/libraries/README.md)

開啟終端,導航到專案資料夾下面,執行命令 build.cmd clr+libs -rc Release
如果不想看到 VS 裡滿屏的紅色波浪線的話,一定要先做這一步。

這次我們需要修改的程式碼位於 System.Net.Http.Json 名稱空間下,在對應資料夾裡找到解決方案檔案,用 VS 開啟就可以。

可以看到裡面的檔案排布十分有規律,複製 Post 的檔案然後批量改成 Patch。

注意到一個問題,HttpClient.PatchAsync 在 .net46 和 .netstandrad 裡是沒有的,只能想辦法相容了(開發任務突然增加)。

之前我是沒有做過相容多個 SDK 的專案的,只能先看看同專案下面其他方法是如何操作的,觀察到 csproj 裡有這樣的程式碼:

用 Condition 選擇性編譯了一些檔案,那麼這裡就可以將 HttpClient.PatchAsync 反向遷移回去,搜尋一下目前的實現,然後複製貼上為 HttpClientJsonExtensions.netstandard.cs

private static Task<HttpResponseMessage> PatchAsync(this HttpClient client, string? requestUri, HttpContent content, CancellationToken cancellationToken)
{
    Uri? uri = string.IsNullOrEmpty(requestUri) ? null : new Uri(requestUri, UriKind.RelativeOrAbsolute);
    return client.PatchAsync(uri, content, cancellationToken);
}

private static Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri? requestUri, HttpContent content, CancellationToken cancellationToken)
{
    // HttpClient.PatchAsync is not available in .NET standard and NET462
    HttpRequestMessage request = new HttpRequestMessage(HttpPatch, requestUri) { Content = content };
    return client.SendAsync(request, cancellationToken);
}

(突然想到,如果我宣告為 public 是不是順便就給 .netstandard2.0 提供了 PatchAsync 方法呢?)

修復編譯錯誤之後,在 ref 裡面新增方法宣告(同樣也是複製貼上替換)。

接下來就是寫測試,複製 POST 方法的測試然後改成 PATCH 就行了(CVH 大法好)。

然後提交 PR 就 ok 了,當然 PR review 過程也比較曲折,有興趣的可以看一下開頭 PR 裡的 Conversation,對我多年不用的英語寫作提出了巨大考驗。

最近有很多博主都喜歡在最後放自己的微信公眾號、打賞連結之類的。作為 N 年前遷移部落格園部落格系統到 .Net Core 的始作俑者(一系列 故障公告),大家多多使用部落格園寫博文就是對我最好的支援了 ╰(°▽°)╯。

另,有點想像 The Old New Thing 一樣寫一些部落格園開發中遇到的好玩事情,不知道有沒有人想看hhhh。(dudu 不要打我hhh)

相關文章