HttpClientの使ってHTTP GET/PUT/POST/DELETEのWeb APIをコールする初歩的なアプリを作成した。
作成手順を紹介する。
チュートリアル的な内容
HttpClientを使うのが、初めてだった。チュートリアルやサンプルコードを検索したが、私の期待に沿うものがなかった(検索結果は下記表の通り)。
サーバアプリのサンプルが過剰だった クライアントと通信するサーバが必要になる。 非公式のチュートリアル(リンク) を調べると、サーバアプリはDBアクセスを伴うコード例が多い。クライントからWeb APIをコールする方法を学ぶことが目的なので、DBアクセスなどは不要。準備するのもコストなので、サーバ側は極力シンプルにしたい。 非公式のチュートリアル(リンク) がGET/PUTのみで、情報不足。 サーバを準備しなくても、動作確認できるチュートリアルもあったが、サンプルがGET/PUTのみ。C#9.0の記法が混ざっている点も厄介。 自動生成コードを利用するため、特別な知識は不要。(2)Web APIクライアントアプリを作成する。
(3)Visual Studioを複数立ち上げて、サーバとクライアントをデバック実行して動作確認する。
(1)ASP.NET Coreで単純なサーバアプリを作る ASP.NET Coreでプロジェクトを作成する。
ソリューションの名前は「SimpleWebServer」にした。
※名前は任意
学習目的で自分PCで動作確認するだけなので、
HTTPS用の構成のチェックを外した
。
プロジェクトを生成する。
自動生成コードを確認する。
生成されたプロジェクトのControllersフォルダ直下に
ValuesController.cs
が存在することを確認する。
実装内容は下記の通り。
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SimpleWebServer.Controllers
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
return new string[] { "value1", "value2" };
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get( int id )
return "value";
// POST api/values
[HttpPost]
public void Post( [FromBody] string value )
// PUT api/values/5
[HttpPut("{id}")]
public void Put( int id, [FromBody] string value )
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete( int id )
http://localhost:19691/api/values//{id}
public ActionResult Get( int id )
idの有無で引、呼び出される関数か識別される。
http://localhost:19691/api/values
public void Post( [FromBody] string value )
本記事では、HTTPのbodyの書式(Content-Typeヘッダ)は「application/json(JSON形式)」で渡す。
valueにJSON文字列が格納される。
http://localhost:19691/api/values/{id}
public void Put( int id, [FromBody] string value )
本記事では、HTTPのbodyの書式(Content-Typeヘッダ)は「application/json(JSON形式)」で渡す。
valueにJSON文字列が格納される。
DELETE
http://localhost:19691/api/values/{id}
public void Delete( int id )
var valueApi = new WebApiClient();
await valueApi.GetAsync();
await valueApi.PutAsync();
await valueApi.PostAsync();
await valueApi.DeleteAsync();
/// <summary>
/// Web APIクライアント
/// </summary>
public class WebApiClient
/// <summary>
/// HTTPクライアント
/// </summary>
/// <remarks>
/// IDisposableを継承しているが、usingで囲わないこと
/// 要求ごとにインスタンス化すると、ソケットが枯渇する懸念があるため、避けたほうが良い。
/// 参考
/// 下記の[HttpClientを作成して初期化する]を参照
/// https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
/// InfoQでも言及されている
/// https://www.infoq.com/jp/news/2016/09/HttpClient/
/// </remarks>
private static HttpClient Client = new HttpClient();
/// <summary>
/// GETメソッドをコールする
/// </summary>
/// <returns></returns>
public async Task GetAsync()
//HTTP GET要求を送信する
Console.WriteLine("Call GET api/values");
var resource = await Client.GetAsync("http://localhost:19691/api/values");
//ステータス異常の時に例外をスルーする
resource.EnsureSuccessStatusCode();
//HTTP応答を取得して表示する
var responseBody = await resource.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
catch(Exception e)
Console.WriteLine(e.ToString());
Console.WriteLine("End");
/// <summary>
/// PUTメソッドをコールする
/// </summary>
/// <returns></returns>
public async Task PutAsync()
//HTTP PUT要求を送信する
Console.WriteLine("Call PUT api/values/5");
var testInput = "TestMessage";
var jsonString = JsonConvert.SerializeObject(testInput);
var data = new StringContent(jsonString, Encoding.UTF8, mediaType: "application/json");
var response = await Client.PutAsync("http://localhost:19691/api/values/5", data);
response.EnsureSuccessStatusCode();
catch(Exception e)
Console.WriteLine(e.ToString());
Console.WriteLine("End");
/// <summary>
/// POSTメソッドをコールする
/// </summary>
/// <returns></returns>
public async Task PostAsync()
//HTTP POST要求を送信する
Console.WriteLine("Call POST api/values");
var testInput = "PostMessage";
var jsonString = JsonConvert.SerializeObject(testInput);
var data = new StringContent(jsonString, Encoding.UTF8, mediaType: "application/json");
var response = await Client.PostAsync("http://localhost:19691/api/values", data);
response.EnsureSuccessStatusCode();
catch(Exception e)
Console.WriteLine(e.ToString());
Console.WriteLine("End");
/// <summary>
/// DELETEメソッドをコールする
/// </summary>
/// <returns></returns>
public async Task DeleteAsync()
//HTTP DELETE要求を送信する
Console.WriteLine("Call DELETE api/values/5");
var response = await Client.DeleteAsync("http://localhost:19691/api/values/5");
response.EnsureSuccessStatusCode();
catch(Exception e)
Console.WriteLine(e.ToString());
Console.WriteLine("End");
// PUT api/values/5
[HttpPut("{id}")]
public void Put( int id, [FromBody] string value ){}
// POST api/values
[HttpPost]
public void Post( [FromBody] string value ){}
// DELETE api/values/5
[HttpDelete("{id}")]
public void Delete( int id ){}
クライアントを実行する。
GETメソッドをコール
サーバ側のGETメソッドが呼ばれていたら、OKです。
サーバ側で返した下記文字列(※)はHTTP応答に付与されます。
※"value1", "value2"
クライアント側でHTTP応答を読み取ると、サーバで返した文字列が表示される。
今回は勉強のため、HttpClientに標準で定義されたメソッドのみを利用した。
記事では触れていないが、実装をより良くする手法として下記2つがある'次にクライアントを作るときは、組み込みたいと思う)。
(1)Microsoftが提供しているパッケージを使う。
例えば、Microsoft.Asp.Net.WebApi.Clientなど。
HttpClentの拡張メソッドが定義されているため、もっと楽に実装できそう。
(2)IHttpClientFactoryを使う。こちらに解説記事があるため、ここでは触れない。
ZetCode C# HttpClient
非公式のC# HttpClientのチュートリアル(英語)。
サーバが準備されており、サンプルソースを書いて動かせる点が良かった。
GET/PUTのみなのが、物足りない。C#9.0の記法が混ざっていることも厄介だった。
ASP.NET Coreを利用するためのVisual Studio 2019のインストール方法
QiitaにあったASP.NET Coreのインストール手順の記事。
.NET クライアントから Web API を呼び出す
Microsoftの公式ドキュメント ASP.NET Web APIガイダンス。Microsoft.Asp.Net.WebApi.Clientパッケージを用いたWeb Apiクライアントの作成方法が記載されている。本記事の次のステップとして、この実装を真似ると良いと思う。
開発者を苦しめる.NETのHttpClientのバグと紛らわしいドキュメント
InfoQの記事。HttpClientを使う上での注意点について述べられている。
HttpClientをusingで囲わないでください
Qiitaの記事。タイトル通りの内容。
IHttpClientFactory を使って今はこれ一択と思った話
IHttpFactoryを紹介したQiitaの記事。
C# 今更ですが、HttpClientを使う
HttpClientの使い方をまとめたQiitaの記事。
HttpClientのBaseAddressを使う方法
HttpClientのBaseAddressプロパティに関する記事