C#: HttpClientを使った様々なPOST送信サンプル

概要

  • HttpClientを使用して、テキスト、JSON、画像、マルチパートのコンテンツをHTTPで送信するサンプルを紹介します。
  • 使用環境は次の通りです。
    OSWindows 10(64ビット)
    IDEMicrosoft Visual Studio Community 2022(17.6.0)
    言語C#(10.0) + .NET6

サンプル

  • サンプルはgithubで公開しています。
  • ASP.NET(.NET6)では、IHttpClientFactoryから取得したHttpClientの使用が推奨されてるので、その想定の例になっています。詳細はリファレンスをご覧ください。
  • HTTP要求のイメージは、こちらで紹介している仕組みで文字列にダンプしています。
    (Hostヘッダは含まれていません。日本語を含む非印刷可能文字は.になっており、本稿では適当に間引いています。)
    NDW*

    HttpClientで使用するHttpRequestMessage, HttpResponseMessageから生HTT…

フォームのPOST

  • FormUrlEncodedContentを使用してフォーム(キー=値)を送信できます。
    var targetUri = new Uri("https://...");
    
    var forms = new Dictionary<string, string>()
    {
        {"key1", "値1" }, { "key2", "1234"}
    };
    using var content = new FormUrlEncodedContent(forms); // "application/x-www-form-urlencoded"
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = content
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • 生成されるHTTP要求のイメージは次の通りです。
    POST /api/DummyApi?body=image HTTP/1.1
    traceparent: 00-96ba339be5710a0462fbb31c69de18af-917ffcc4b4fd5f1b-00
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 33
    
    key1=%E5%80%A4%EF%BC%91&key2=1234

テキストのPOST

  • StringContentを使用してテキストを送信できます。
    コンテンツ内容としてJSON文字列、コンテンツタイプとして”text/json”を指定してJSONを送信することもできます。コンテンツタイプに関して、主要なものはmdn、完全なものはIANAをご覧ください。

    var targetUri = new Uri("https://...");
    
    var data = "key1=値1, key2=1234";
    using var content = new StringContent(data); // "text/plain; charset=utf-8"
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = content
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • 生成されるHTTP要求のイメージは次の通りです。
    POST /api/DummyApi?body=json HTTP/1.1
    traceparent: 00-808d7e9be49a229396da905b157a4155-312f6aa1d6bf94f0-00
    Content-Type: text/plain; charset=utf-8
    Content-Length: 22
    
    key1=......, key2=1234

JSONのPOST

  • JsonContentを使用して、C#のオブジェクトから変換したJSONを送信できます。
    JsonSerializerでJSON文字列を生成し、前述のようにStringContentで送信することもできます。
    コンテンツタイプに関して、主要なものはmdn、完全なものはIANAをご覧ください。

    var targetUri = new Uri("https://...");
    
    var data = new Dictionary<string, object>() {
        {"key1", "値1" }, {"key2", 1234}
    };
    using var content = JsonContent.Create(data); // "application/json; charset=utf-8"
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = content
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • 生成されるHTTP要求のイメージは次の通りです。
    POST /api/DummyApi?body=json HTTP/1.1
    Transfer-Encoding: chunked
    traceparent: 00-887f351c976ccd61fc2153caf25bab66-ffedd1bd14c4b825-00
    Content-Type: application/json; charset=utf-8
    
    {"key1":"\u5024\uFF11","key2":1234}

画像等のバイナリのPOST

  • バイト配列のコンテンツの場合、ByteArrayContentを使用して送信できます。
    必要に応じてコンテンツタイプを指定します。コンテンツタイプに関して、主要なものはmdn、完全なものはIANAをご覧ください。

    var targetUri = new Uri("https://...");
    
    using var content = new ByteArrayContent(_image1bytes);
    content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = content
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • ストリームのコンテンツの場合、StreamContentを使用して送信できます。
    var targetUri = new Uri("https://...");
    
    using var stream = new MemoryStream(_image2bytes);
    using var content = new StreamContent(stream);
    content.Headers.ContentType = new MediaTypeHeaderValue("image/png");
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = content
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • 生成されるHTTP要求のイメージは次の通りです。
    POST /api/DummyApi HTTP/1.1
    traceparent: 00-ae4b8ae4734f23d6817ed12b22a256dc-f8103d3e7300c460-00
    Content-Type: image/png
    Content-Length: 233
    
    .PNG
    .
    ...
    IHDR...@...@......iq.....sRGB.........gAMA......a....
    ...o...j..j..j..j..j..j..j..j..j..j..j..j..j..j..j..j.

マルチパートのPOST

  • MultipartFormDataContentを使用して、マルチパートのデータを送信できます。
    マルチパートには、前述のStringContent, StreamContent等のクラスを使用して様々なコンテンツを追加できます。
    コンテンツタイプに関して、主要なものはmdn、完全なものはIANAをご覧ください。

    var targetUri = new Uri("https://...");
    
    using var part1 = new StringContent("値1");
    using var part2 = new ByteArrayContent(_image1bytes);
    part2.Headers.ContentType = new MediaTypeHeaderValue("image/png");
    using var part3 = new ByteArrayContent(_image2bytes);
    part3.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
    using var multipartContent = new MultipartFormDataContent
    {
        { part1, "key1" },
        { part2, "key2", "sample1.png" },
        { part3, "key3", "サンプル2.jpg" }
    };
    using var req = new HttpRequestMessage()
    {
        Method = HttpMethod.Post,
        RequestUri = targetUri,
        Content = multipartContent
    };
    
    var httpClient = _httpClientFactory.CreateClient();
    using var res = await httpClient.SendAsync(req);
  • 生成されるHTTP要求のイメージは次の通りです。
    Content-Dispositionでファイル名を指定する場合、13行目のようにfilenameの値に引用符がない場合があり、一部のシステムではエラーになる場合があります。詳細はこちらをご覧ください。

    POST /api/DummyApi?body=json HTTP/1.1
    traceparent: 00-702d4c28ac18059b523d842fba5a6dc3-da082db5550978aa-00
    Content-Type: multipart/form-data; boundary="b702b5c5-ebc3-4149-8f55-25664e56f329"
    Content-Length: 1605
    
    --b702b5c5-ebc3-4149-8f55-25664e56f329
    Content-Type: text/plain; charset=utf-8
    Content-Disposition: form-data; name=key1
    
    ......
    --b702b5c5-ebc3-4149-8f55-25664e56f329
    Content-Type: image/png
    Content-Disposition: form-data; name=key2; filename=sample1.png; filename*=utf-8''sample1.png
    
    .PNG
    .
    ...o...j..j..j..j..j..j..j..j..j..j..j..j..j....j..j..j..j..j....Y...........IEND.B`.
    --b702b5c5-ebc3-4149-8f55-25664e56f329
    Content-Type: image/jpeg
    Content-Disposition: form-data; name=key3; filename="=?utf-8?B?44K144Oz44OX44Or77ySLmpwZw==?="; filename*=utf-8''%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%EF%BC%92.jpg
    
    ......JFIF.....`.`.....fExif..MM.*.................
    .....................}........!1A..Qa."q.2....#B...R..$3br..
    .....%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz.....................
    ..?..z(..x?...(...(...(...(...(...(...(...(...(...(...(...(...(...(...(....
    --b702b5c5-ebc3-4149-8f55-25664e56f329--