取用 RESTful Web 服務

Download Sample 下載範例

將 Web 服務整合到應用程式是常見的案例。 本文示範如何從 Xamarin.Forms 應用程式取用 RESTful Web 服務。

具象狀態傳輸 (REST) 是建立 Web 服務的架構樣式。 REST 要求是使用網頁瀏覽器用來取出網頁以及將資料傳送至伺服器的相同 HTTP 指令動詞,透過 HTTP 進行。 指令動詞如下:

  • GET - 這項作業用來從 Web 服務取出資料。
  • POST - 這項作業用來在 Web 服務上建立新的資料項目。
  • PUT - 這項作業用來在 Web 服務上更新資料項目。
  • PATCH - 這項作業用來透過描述有關應該如何修改項目的一組指示,更新 Web 服務上的資料項目。 範例應用程式中未使用此指令動詞。
  • DELETE - 這項作業用來在 Web 服務上刪除資料項目。

遵守 REST 的 Web 服務 API 稱為 RESTful API,並使用下列項目定義:

  • 基底 URI。
  • HTTP 方法,例如 GET、POST、PUT、PATCH 或 DELETE。
  • 數據的媒體類型,例如 JavaScript 物件表示法(JSON)。

RESTful Web 服務通常會使用 JSON 訊息將數據傳回用戶端。 JSON 是一種以文字為基礎的數據交換格式,會產生精簡承載,這會導致傳送數據時帶寬需求降低。 範例應用程式會使用 開放原始碼 NewtonSoft JSON.NET 連結庫來串行化和還原串行化訊息。

REST 的簡單性有助於它成為在行動應用程式中存取 Web 服務的主要方法。

執行範例應用程式時,它會連線到本機裝載的 REST 服務,如下列螢幕快照所示:

Sample Application

注意

在 iOS 9 和更新版本中,應用程式傳輸安全性 (ATS) 會強制執行因特網資源(例如應用程式後端伺服器)與應用程式之間的安全連線,以防止意外洩漏敏感性資訊。 由於 ATS 預設會在針對 iOS 9 建置的應用程式中啟用,因此所有連線都會受限於 ATS 安全性需求。 如果連線不符合這些需求,它們將會失敗併發生例外狀況。

如果無法使用 HTTPS 通訊協定和保護因特網資源的通訊,則可以退出宣告 ATS 。 您可以藉由更新應用程式的 Info.plist 檔案來達成此目的。 如需詳細資訊,請參閱 應用程式傳輸安全性

取用 Web 服務

REST 服務是使用 ASP.NET Core 撰寫,並提供下列作業:

作業 HTTP 方法 相對 URI 參數
取得待辦事項的清單 GET /api/todoitems/
建立新的 To-do 專案 POST /api/todoitems/ JSON 格式化的 TodoItem
更新待辦事項 PUT /api/todoitems/ JSON 格式化的 TodoItem
刪除待辦事項 DELETE /api/todoitems/{id}

大部分 URI 都包含 TodoItem 路徑中的識別碼。 例如,若要刪除 TodoItem 識別碼為 6bb8a868-dba1-4f1a-93b7-24ebce87e243的 ,用戶端會將 DELETE 要求傳送至 http://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243。 如需範例應用程式中使用之數據模型的詳細資訊,請參閱 將數據模型化。

當 Web API 架構收到要求時,它會將要求路由傳送至動作。 這些動作只是類別中的 TodoItemsController 公用方法。 架構會使用路由中間件來比對傳入要求的URL,並將其對應至動作。 REST API 應該使用屬性路由將應用程式的功能模型作為一組資源,其作業是以 HTTP 動詞表示。 屬性路由使用一組屬性,將動作直接對應至路由範本。 如需屬性路由的詳細資訊,請參閱 REST API 的屬性路由。 如需使用 ASP.NET Core 建置 REST 服務的詳細資訊,請參閱 建立原生行動應用程式的後端服務。

類別 HttpClient 是用來透過 HTTP 傳送和接收要求。 它提供從 URI 識別資源傳送 HTTP 要求和接收 HTTP 回應的功能。 每個要求都會以異步操作的形式傳送。 如需異步操作的詳細資訊,請參閱 異步支援概觀

類別 HttpResponseMessage 代表在提出 HTTP 要求之後,從 Web 服務接收的 HTTP 回應消息。 其中包含回應的資訊,包括狀態碼、標頭和任何本文。 類別 HttpContent 代表 HTTP 主體和內容標頭,例如 Content-TypeContent-Encoding。 視數據的格式而定,可以使用 和 ReadAsByteArrayAsyncReadAsStringAsync任何ReadAs方法讀取內容。

建立 HTTPClient 物件

HttpClient實例會在類別層級宣告,以便只要應用程式需要提出 HTTP 要求,物件就會存留,如下列程式代碼範例所示:

public class RestService : IRestService
{
  HttpClient client;
  ...

  public RestService ()
  {
    client = new HttpClient ();
    ...
  }
  ...
}

取出資料

方法 HttpClient.GetAsync 可用來將 GET 要求傳送至 URI 所指定的 Web 服務,然後接收來自 Web 服務的回應,如下列程式代碼範例所示:

public async Task<List<TodoItem>> RefreshDataAsync ()
{
  ...
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));
  ...
  HttpResponseMessage response = await client.GetAsync (uri);
  if (response.IsSuccessStatusCode)
  {
      string content = await response.Content.ReadAsStringAsync ();
      Items = JsonSerializer.Deserialize<List<TodoItem>>(content, serializerOptions);
  }
  ...
}

REST 服務會在 屬性中 HttpResponseMessage.IsSuccessStatusCode 傳送 HTTP 狀態代碼,以指出 HTTP 要求成功或失敗。 針對這項作業,REST 服務會在回應中傳送 HTTP 狀態代碼 200 (OK),這表示要求成功,且要求的資訊位於回應中。

如果 HTTP 作業成功,則會讀取回應的內容,以供顯示。 屬性 HttpResponseMessage.Content 代表 HTTP 回應的內容,而 HttpContent.ReadAsStringAsync 方法會以異步方式將 HTTP 內容寫入字串。 然後,此內容會從 JSON 還原串行化為 List 實體的 TodoItem

警告

ReadAsStringAsync使用方法來擷取大型回應可能會對效能造成負面影響。 在這種情況下,應該直接還原串行化回應,以避免必須完全緩衝處理它。

建立資料

方法 HttpClient.PostAsync 可用來將 POST 要求傳送至 URI 所指定的 Web 服務,然後接收來自 Web 服務的回應,如下列程式代碼範例所示:

public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));

  ...
  string json = JsonSerializer.Serialize<TodoItem>(item, serializerOptions);
  StringContent content = new StringContent (json, Encoding.UTF8, "application/json");

  HttpResponseMessage response = null;
  if (isNewItem)
  {
    response = await client.PostAsync (uri, content);
  }
  ...

  if (response.IsSuccessStatusCode)
  {
    Debug.WriteLine (@"\tTodoItem successfully saved.");
  }
  ...
}

實例 TodoItem 會串行化為 JSON 承載,以便傳送至 Web 服務。 接著,此承載會內嵌在 HTTP 內容的主體中,該內容會在使用 PostAsync 方法提出要求之前傳送至 Web 服務。

REST 服務會在 屬性中 HttpResponseMessage.IsSuccessStatusCode 傳送 HTTP 狀態代碼,以指出 HTTP 要求成功或失敗。 此作業的常見回應如下:

  • 201 (CREATED) – 要求會導致在傳送回應之前建立新的資源。
  • 400 (BAD REQUEST) - 伺服器無法理解要求。
  • 409 (CONFLICT) - 因為伺服器上的衝突,所以無法執行要求。

更新資料

方法 HttpClient.PutAsync 可用來將 PUT 要求傳送至 URI 所指定的 Web 服務,然後接收來自 Web 服務的回應,如下列程式代碼範例所示:

public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
  ...
  response = await client.PutAsync (uri, content);
  ...
}

方法的 PutAsync 作業與用來在 Web 服務中建立數據的方法相同 PostAsync 。 不過,從 Web 服務傳送的可能回應會有所不同。

REST 服務會在 屬性中 HttpResponseMessage.IsSuccessStatusCode 傳送 HTTP 狀態代碼,以指出 HTTP 要求成功或失敗。 此作業的常見回應如下:

  • 204 (NO CONTENT) – 要求已成功處理,且回應刻意為空白。
  • 400 (BAD REQUEST) - 伺服器無法理解要求。
  • 404 (找不到) - 要求的資源不存在於伺服器上。

刪除資料

方法 HttpClient.DeleteAsync 可用來將 DELETE 要求傳送至 URI 所指定的 Web 服務,然後接收來自 Web 服務的回應,如下列程式代碼範例所示:

public async Task DeleteTodoItemAsync (string id)
{
  Uri uri = new Uri (string.Format (Constants.TodoItemsUrl, id));
  ...
  HttpResponseMessage response = await client.DeleteAsync (uri);
  if (response.IsSuccessStatusCode)
  {
    Debug.WriteLine (@"\tTodoItem successfully deleted.");
  }
  ...
}

REST 服務會在 屬性中 HttpResponseMessage.IsSuccessStatusCode 傳送 HTTP 狀態代碼,以指出 HTTP 要求成功或失敗。 此作業的常見回應如下:

  • 204 (NO CONTENT) – 要求已成功處理,且回應刻意為空白。
  • 400 (BAD REQUEST) - 伺服器無法理解要求。
  • 404 (找不到) - 要求的資源不存在於伺服器上。

本機開發

如果您要使用 ASP.NET Core Web API 等架構在本機開發 REST Web 服務,您可以同時對 Web 服務和行動應用程式進行偵錯。 在此案例中,您必須為iOS模擬器和Android模擬器啟用純文字 HTTP 流量。 如需設定專案以允許通訊的資訊,請參閱本機 Web 服務 連線。