使用 HttpClient 取用 REST 服務
許多新式 Web 服務均實作 REST 架構。 此結構可讓 Web 服務透過一系列妥善定義的端點來公開作業和資料。 用戶端應用程式傳送至 REST Web 服務以擷取、修改、建立或刪除資料的要求,會使用一組預先定義的動詞。 REST Web 服務會以標準方式回應這些要求。 此方法可讓您更輕鬆地建構用戶端應用程式。
REST 模型建置於 HTTP 通訊協定之上。 .NET MAUI 應用程式可使用 HttpClient
類別將要求傳送至 REST Web 服務。 在此單元中,您將了解 HttpClient
,以及如何用它與 REST Web 服務互動。
什麼是 HttpClient 類別?
HttpClient
是一個 .NET 類別,可讓應用程式用來傳送 HTTP 要求,以及接收來自 REST Web 服務的 HTTP 回應。 一組 URI 會識別 Web 服務公開的資源。 URI 會結合 Web 服務的位址,以及該位址上可用資源的名稱。
HttpClient
類別會使用以工作為基礎的 API 來支援效能,並允許您存取要求訊息中的資訊,例如 HTTP 標頭和狀態碼,以及包含要傳送及接收之實際資料的訊息本文。
HttpClient
類別會在 System.Net.Http
命名空間中提供。 應用程式可使用預設建構函式來建立 HttpClient
物件:
using System.Net.Http;
...
var client = new HttpClient();
使用 HttpClient 物件執行 CRUD 作業
REST Web 服務可讓用戶端透過一組 HTTP 動詞對資料執行作業。 HTTP 動詞的工作是指出要對資源執行的動作。 HTTP 動詞命令有很多個,但是最常見的四個為:POST
、GET
、PUT
和 DELETE
。 服務可以實作這些動詞,讓用戶端應用程式執行建立、讀取、更新和刪除 (CRUD) 作業以管理物件的生命週期,如下所示:
POST
動詞命令表示您想要建立新資源。GET
動詞命令表示您想要擷取資源。PUT
動詞命令表示您想要更新資源。DELETE
動詞命令表示您想要刪除資源。
使用 HttpClient 建立新資源
若要使用 HttpClient
建立新的資源,您可以使用 SendAsync
方法對其傳遞 HttpRequestMessage
物件。
HttpRequestMessage
旨在為傳送至 Web 服務的要求建立模型。 您可以指定 HTTP 動詞、Web 服務的 URL,並填入任何要透過 HttpRequestMessage.Content
屬性傳送的承載。
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);
message.Content = JsonContent.Create<Part>(part);
HttpResponseMessage response = await client.SendAsync(message);
此程式碼片段會執行下列工作:
- 它會建立名為
HttpClient
client 的 執行個體,用來傳送訊息。 - 它會建立名為
HttpRequestMessage
message 的 執行個體,用來建立訊息的模型。 message 具有 HTTP 動詞和 URL。 - 它會使用
JsonContent.Create
函式來設定HttpRequestMessage
的Content
屬性。 該函式會自動將 part 變數序列化為適合傳送至 Web 服務的 JSON。 - 它會使用
HttpClient
物件來傳送訊息。 會傳回一個HttpResponseMessage
,其中包含狀態碼等資訊和 Web 服務所傳回的資訊。
使用 HttpClient 讀取資源
您可以使用先前所述的相同技術從 Web 服務中讀取資源,但初始化 HttpRequestMessage
時須使用 HttpMethod.Get
。 不過,HttpClient
有數種提供捷徑的簡便方法。
若要使用 HTTPClient
來讀取資源,請使用 GetStringAsync
方法,下一個範例所示:
HttpClient client = new HttpClient();
string text = await client.GetStringAsync("https://...");
GetStringAsync
方法採用參考資源的 URI,並以字串形式傳回回應。 字串回應是應用程式要求的資源。 回應-資料格式是所要求服務的預設值,例如 JSON 或 XML。 應用程式可藉由新增 MediaTypeWithQualityHeaderValue
標頭向 Web 服務指出資料必須以特定格式傳回。 例如,應用程式若要求以 JSON 格式傳回資料,可以使用下列程式碼:
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
在此範例中,結果會以字串的形式傳回,並且只包含回應訊息本文。 若要取得包括標頭、本文和狀態碼在內的完整回應,請呼叫 GetAsync
方法。 資料會以 HttpResponseMessage
物件的形式傳回。
使用 HttpClient 更新資源
若要使用 HttpClient
來更新資源,請使用以 PUT 動詞初始化的 HttpRequestMessage
。 下列程式碼與建立新資源所需的程式碼類似:
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, url);
message.Content = JsonContent.Create<Part>(part);
HttpResponseMessage response = await client.SendAsync(message);
注意
POST
與 PUT
之間的根本差異在於冪等性。 如果您重複相同的 PUT
要求數次,則相同的資源將會以相同的資料更新,且效果會與僅傳送一次要求相同。 如果您將相同的 POST
要求發出多次,結果將會是 REST 服務建立資源的多個複本。
使用 HttpClient 刪除資源
若要使用 HttpClient
來刪除資源,請使用以 DELETE 動詞初始化的 HttpRequestMessage
呼叫 SendAsync
:
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Delete, url);
HttpResponseMessage response = await client.SendAsync(message);
回應包含標頭、狀態碼和已刪除的物件。
處理來自要求的回應
所有 HTTP 要求都會傳回回應訊息。 回應中的資料取決於應用程式傳送的動詞。 例如,HTTP GET
要求的回應本文包含所要求資源的資料。
POST
要求的回應本文傳回已建立資源的複本,但 PUT
要求的回應本文應該是空的。
您應隨時檢查並處理回應訊息中的狀態碼。 如果此狀態碼屬於 200 範圍 (200、201、202 等),則作業被視為已成功,但後續可能需要進一步的資訊。
屬於 300 範圍的狀態碼表示要求可能已由 Web 服務重新導向至不同的位址,這可能是由於資源移至不同的位置所致。
屬於 400 範圍的狀態碼表示用戶端或應用程式錯誤。 例如,狀態碼 403 表示 Web 服務要求驗證使用者,但應用程式尚未進行此驗證。 當應用程式嘗試存取不存在的資源時,將會出現狀態碼 404。
屬於 500 範圍的狀態碼表示伺服器端錯誤,例如服務無法使用或太忙碌,因而無法處理要求。
透過 HttpClient
物件提交的要求所傳回的 HttpResponseMessage
物件,可大幅降低處理不同狀態碼時的複雜度。 此程式碼片段說明如何驗證回應訊息中的狀態碼是否顯示為成功,以及如何處理表示某種失敗的狀態碼。
static readonly HttpClient client = new HttpClient();
...
// Call asynchronous network methods in a try/catch block to handle exceptions.
try
{
//... Initiate the HttpRequest
HttpResponseMessage response = await client.SendAsync(msg);
response.EnsureSuccessStatusCode(); // Check that the status code is in the 200 range. Throw an HttpRequestException if not
string responseBody = await response.Content.ReadAsStringAsync();
... // Handle the response
}
catch(HttpRequestException e)
{
... // Handle any status codes that indicate an error.
// The status code is available in the field e.StatusCode
}