RESTful Web サービスの使用
Web サービスをアプリケーションに統合することは、一般的なシナリオの 1 つです。 この記事では、Xamarin.Forms アプリケーションから RESTful Web サービスを使用する方法について説明します。
Representational State Transfer (REST) は、Web サービスをビルドするためのアーキテクチャ スタイルです。 REST 要求は、Web ブラウザーが Web ページの取得やサーバーへのデータの送信に使用するのと同じ HTTP 動詞を使用して HTTP 経由で実行されます。 次の動詞があります。
- GET – この操作は、Web サービスからデータを取得するために使用されます。
- POST – この操作は、Web サービスに新しいデータ項目を作成するために使用されます。
- PUT – この操作は、Web サービスのデータ項目を更新するために使用されます。
- PATCH – この操作は、項目の変更方法に関する一連の命令を記述することにより、Web サービスのデータ項目を更新するために使用されます。 この動詞は、サンプル アプリケーションでは使用されていません。
- DELETE – この操作は、Web サービスのデータ項目を削除するために使用されます。
REST に準拠する Web サービス API は RESTful API と呼ばれ、次のものを使用して定義されます。
- ベース URI。
- GET、POST、PUT、PATCH、DELETE などの HTTP メソッド。
- JavaScript Object Notation (JSON) などの、データのメディアの種類。
RESTful Web サービスにより、通常は JSON メッセージを使用してクライアントにデータが返されます。 JSON は、データの送受信時に帯域幅要件を減らせる、コンパクトなペイロードを生成するテキスト ベースのデータ交換形式です。 サンプル アプリケーションでは、オープンソース NewtonSoft JSON.NET ライブラリを使用してメッセージをシリアル化/逆シリアル化します。
REST は、そのシンプルさもあって、モバイル アプリケーションで Web サービスにアクセスするための主要な方法となっています。
サンプル アプリケーションが実行されると、次のスクリーンショットに示すように、ローカルでホストされている REST サービスに接続されます。
Note
iOS 9 以降では、App Transport Security (ATS) により、インターネット リソース (アプリのバックエンド サーバーなど) とアプリの間にセキュリティで保護された接続が適用されるため、機密情報の漏洩が防止されます。 iOS 9 用に構築されたアプリ内では ATS が既定で有効なため、すべての接続が ATS セキュリティ要件の対象となります。 接続がこれらの要件を満たさない場合は、例外を伴って失敗します。
HTTPS プロトコルを使用してインターネット リソースの通信をセキュリティで保護できない場合は、ATS をオプトアウトできます。 これは、アプリの Info.plist ファイルを更新することで実現できます。 詳細については、アプリ トランスポート セキュリティに関する記事を参照してください。
Web サービスを使用する
REST サービスは、ASP.NET Core を使用して記述され、次の操作を提供します。
操作 | HTTP メソッド | 相対 URI | パラメーター |
---|---|---|---|
To Do アイテムのリストの取得 | GET | /api/todoitems/ | |
新しい To Do 項目を作成する | 投稿 | /api/todoitems/ | JSON 形式の ToDo 項目 |
To Do アイテムの更新 | PUT | /api/todoitems/ | JSON 形式の ToDo 項目 |
To Do アイテムの削除 | DELETE | /api/todoitems/{id} |
URI の大半には、パスに TodoItem
ID が含まれています。 たとえば、ID が 6bb8a868-dba1-4f1a-93b7-24ebce87e243
の TodoItem
を削除するために、クライアントは DELETE 要求を http://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243
に送信します。 サンプル アプリケーションで使われるデータ モデルの詳細については、データのモデリングに関する記事を参照してください。
要求を受信すると Web API フレームワークは、要求をアクションにルーティングします。 これらのアクションは、TodoItemsController
クラスの単なるパブリック メソッドです。 フレームワークは、ルーティング ミドルウェアを使って、受信した要求の URL を照合し、アクションにマップします。 REST API では、属性ルーティングを使用して、HTTP 動詞でその操作が表されるリソースのセットとしてアプリの機能をモデル化する必要があります。 属性ルーティングでは、属性のセットを使ってアクションをルート テンプレートに直接マップします。 属性ルーティングの詳細については、「Attribute routing for REST APIs」をご覧ください。 ASP.NET Core を使用した REST サービスの構築の詳細については、「ネイティブ モバイル アプリケーションのバックエンド サービスの作成」を参照してください。
HttpClient
クラスは、HTTP 経由で要求を送受信するために使用されます。 これは、HTTP 要求を送信し、URI で識別されたリソースから HTTP 応答を受信するための機能を提供します。 これらの各要求は、非同期操作として送信されます。 非同期操作の詳細については、「非同期サポートの概要」を参照してください。
HttpResponseMessage
クラスは、HTTP 要求が行われた後に Web サービスから受信した HTTP 応答メッセージを表します。 これには、状態コード、ヘッダー、本文など、応答に関する情報が含まれます。 HttpContent
クラスは、HTTP 本文とコンテンツ ヘッダー (Content-Type
や Content-Encoding
など) を表します。 コンテンツは、データの形式に応じて、ReadAsStringAsync
や ReadAsByteArrayAsync
などの ReadAs
メソッドのどれかを使用して読み取ることができます。
HTTPClient オブジェクトを作成する
次のコード例に示すように、HttpClient
インスタンスはクラスレベルで宣言されているため、アプリケーションが HTTP 要求を行う必要がある限り、オブジェクトは存続します。
public class RestService : IRestService
{
HttpClient client;
...
public RestService ()
{
client = new HttpClient ();
...
}
...
}
データを取得する
次のコード例に示すように、HttpClient.GetAsync
メソッドは、URI で指定された Web サービスに GET 要求を送信した後、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 サービスは、HTTP 要求が成功したか失敗したかを示すために、HttpResponseMessage.IsSuccessStatusCode
プロパティで HTTP 状態コードを送信します。 この操作では、REST サービスは応答に HTTP 状態コード 200 (OK) を送信します。これは、要求が成功し、要求された情報が応答にあることを示します。
HTTP 操作が成功した場合、応答の内容が読み取られます (表示用)。 この HttpResponseMessage.Content
プロパティは HTTP 応答の内容を表し、HttpContent.ReadAsStringAsync
メソッドは HTTP コンテンツを文字列に非同期的に書き込みます。 その後、このコンテンツは JSON から TodoItem
インスタンスの List
に逆シリアル化されます。
警告
ReadAsStringAsync
メソッドを使用して大きな応答を取得すると、パフォーマンスに悪影響を及ぼす可能性があります。 このような状況では、応答を完全にバッファー処理しないように、応答を直接逆シリアル化する必要があります。
データの作成
次のコード例に示すように、HttpClient.PostAsync
メソッドは、URI で指定された Web サービスに POST 要求を送信した後、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
インスタンスは、Web サービスに送信するために JSON ペイロードにシリアル化されます。 このペイロードは、PostAsync
メソッドで要求が行われる前に Web サービスに送信される HTTP コンテンツの本文に埋め込まれます。
REST サービスは、HTTP 要求が成功したか失敗したかを示すために、HttpResponseMessage.IsSuccessStatusCode
プロパティで HTTP 状態コードを送信します。 この操作の一般的な応答は、次のとおりです。
- 201 (CREATED): 応答が送信される前に、要求によって新しいリソースが作成されたことを示します。
- 400 (BAD REQUEST): 要求はサーバーによって認識されません。
- 409 (CONFLICT): サーバー上の競合のために要求を実行できないことを示します。
データの更新
次のコード例に示すように、HttpClient.PutAsync
メソッドは、URI で指定された Web サービスに PUT 要求を送信した後、Web サービスから応答を受信するために使用されます。
public async Task SaveTodoItemAsync (TodoItem item, bool isNewItem = false)
{
...
response = await client.PutAsync (uri, content);
...
}
PutAsync
メソッドの操作は、Web サービスでデータを作成するために使用される PostAsync
メソッドと同じです。 ただし、Web サービスから送信される可能性のある応答は異なります。
REST サービスは、HTTP 要求が成功したか失敗したかを示すために、HttpResponseMessage.IsSuccessStatusCode
プロパティで HTTP 状態コードを送信します。 この操作の一般的な応答は、次のとおりです。
- 204 (NO CONTENT): 要求が正常に処理され、応答が意図的に空白になっていることを示します。
- 400 (BAD REQUEST): 要求はサーバーによって認識されません。
- 404 (NOT FOUND): 要求されたリソースはサーバーに存在しないことを示します。
データの削除
次のコード例に示すように、HttpClient.DeleteAsync
メソッドは、URI で指定された Web サービスに DELETE 要求を送信した後、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 サービスは、HTTP 要求が成功したか失敗したかを示すために、HttpResponseMessage.IsSuccessStatusCode
プロパティで HTTP 状態コードを送信します。 この操作の一般的な応答は、次のとおりです。
- 204 (NO CONTENT): 要求が正常に処理され、応答が意図的に空白になっていることを示します。
- 400 (BAD REQUEST): 要求はサーバーによって認識されません。
- 404 (NOT FOUND): 要求されたリソースはサーバーに存在しないことを示します。
ローカル開発
ASP.NET Core Web API などのフレームワークを使用して REST Web サービスをローカルで開発している場合は、Web サービスとモバイル アプリを同時にデバッグできます。 このシナリオでは、iOS シミュレーターと Android エミュレーターのクリアテキスト HTTP トラフィックを有効にする必要があります。 通信を許可するようにプロジェクトを構成する方法については、「ローカル Web サービスに接続する」を参照してください。