Skip to content

MS_HttpClientUsage

nishi_74322014 edited this page Aug 3, 2026 · 1 revision

HttpClientの類の使い方

概要

.NETクライアントからHTTPリクエストを送る場合、従来は、

使用していたが、こちらは設計が古いもよう。

新しくは、.NET Framework 4.5 では BCL 入りした
System.Net.Http.dll の HttpClientクラスを使用する。

HttpClientFactoryクラス

概要

特徴

HttpClientクラスのハンドラ委任を構成可能。

  • ネーミングや構成を管理
  • HttpClientクラスのライフサイクルを管理
  • クリーン・アーキテクチャっぽく Polly を統合

使い方

基本的な使い方

  • 設定(DI Container に登録)
  • 使う場所で呼び出す

使い方のパターン

  • 基本的には、Controllerに DI(constructor注入)し、
    使う場所で、CreateClient(Factoryメソッド)を呼び出す。
  • Named Clients では、名前を指定して、CreateClient(Factoryメソッド)を呼び出す。
  • TypedClients では、
    • 指定の型に DI する。
    • 型には、以下がある。
      • クラス(constructor注入)
      • インターフェイス(Refit の live interface)

参考

HttpClientクラス

.NET Framework 4.5 で BCL 入りした、高機能で使い勝手がいいAPI。

サンプル

GET

// HttpClient
private static HttpClient _httpClient = new HttpClient();

// 通信用の変数
HttpRequestMessage httpRequestMessage = null;
HttpResponseMessage httpResponseMessage = null;

// HttpRequestMessage (Method & RequestUri)
httpRequestMessage = new HttpRequestMessage
{
    Method = HttpMethod.Get,
    RequestUri = new Uri("http://localhost/・・・"),
};

// HttpRequestMessage (Headers & Content)
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic",
    Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "・・・", "・・・"))));

httpRequestMessage.Headers.ExpectContinue = false;

// HttpResponseMessage
httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage);

response = await httpResponseMessage.Content.ReadAsStringAsync();
return (JObject)JsonConvert.DeserializeObject(response);

移行メモ: 原文のサンプルは RequestUri = new Uri("http://localhost/・・・", と 閉じ括弧が欠けていた(コンパイルできない)。閉じ括弧を補った。

POST

POST については、上記GETのコード

  • Method = HttpMethod.GetMethod = HttpMethod.Post に変更。
  • httpRequestMessage.Content プロパティを設定する。
// HttpRequestMessage (Method & RequestUri)
httpRequestMessage = new HttpRequestMessage
{
    Method = HttpMethod.Post,
    RequestUri = new Uri("http://localhost/・・・"),
};

// HttpRequestMessage (Headers & Content)
httpRequestMessage.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic",
    Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "・・・", "・・・"))));

httpRequestMessage.Content = new FormUrlEncodedContent(
    new Dictionary<string, string>
    {
        { "grant_type", "authorization_code" },
        { "code", code },
        { "redirect_uri", "http://localhost/・・・" },
    });

// HttpResponseMessage
httpResponseMessage = await _httpClient.SendAsync(httpRequestMessage);

response = await httpResponseMessage.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Dictionary<string, string>>(response);

移行メモ(正誤): 原文は redirect_uri の値を System.Web.HttpUtility.HtmlEncode(...) で包んでいたが、 HtmlEncode は HTML 用のエスケープで、フォーム送信値には不要かつ有害 (&&amp; になるなど値が変わる)。 FormUrlEncodedContent が URL エンコードを行うため、生の値を渡せばよい。 URL エンコードを明示したい場合は Uri.EscapeDataString を使う。

JSON

JSONのPOSTについては、
上記コードの httpRequestMessage.Content プロパティにJSON文字列を指定する。

httpRequestMessage.Content = new StringContent(
  JsonConvert.SerializeObject(new
  {
    language = "ja"
  }),
  Encoding.UTF8, "application/json");

※ 現在の .NET では System.Net.Http.Json の拡張メソッド
PostAsJsonAsync / ReadFromJsonAsync)を使えば、
System.Text.Json ベースで同等の処理を簡潔に書ける。

ポイント

Make your HttpClient static

  • 以下の問題があるので、HttpClientは基本的に、
    • static で使用する。
    • 都度、instance化しないこと(適切にdisposeしてもダメ)。
    • これは、都度、instanceすると、ソケットを爆発させるため(TIME_WAIT の枯渇)。

補足: static 化にも副作用があり、 DNS の変更が反映されない(ソケットを掴んだままになる)という逆の問題が起きる。 このため現在は、

  • IHttpClientFactory を使う(ハンドラを一定時間でローテートする)か、
  • SocketsHttpHandler.PooledConnectionLifetime を設定する

のが推奨。「static にする」は問題の半分だけの解になっている点に注意。

認証プロキシを通す場合

以下が参考になる。

デバッグ・プロキシを通す

認証プロキシを通す場合と同じだが、

  • Fiddler

    • 「WebBrowser」はlocalhostでも表示されるが、
    • 「Non-Browser」(≒ HttpClient)はlocalhostが表示されない。

    という(非常に痛い)問題がある。
    WebProxy.BypassProxyOnLocal 辺りの問題と切り分けが困難)

  • 以下の「http://localhost」をhostsファイルで別名に変更すると、\ 「Non-Browser」でも、ログに表示されるようになる。

using System;
using System.Net.Http;

namespace ConsoleApp1
{
    class Program
    {
        //private static readonly string proxyUrl = "http://127.0.0.1:8888";
        //private static readonly string proxyAccount = "account";
        //private static readonly string proxyPassword = "password";
        private static readonly string targetUrl = "http://localhost/iisstart.htm";

        static void Main(string[] args)
        {
            // HttpClientHandlerにProxy情報を設定する
            HttpClientHandler ch = new HttpClientHandler();
            //ch.Proxy = new WebProxy(proxyUrl);
            //ch.Proxy.Credentials = new NetworkCredential(proxyAccount, proxyPassword);
            //ch.UseProxy = true;

            // HttpClientHandlerを用いてHttpClientを生成
            HttpClient client = new HttpClient(ch);
            try
            {
                // GETでレスポンスを取得
                var task = client.GetStringAsync(targetUrl);
                task.Wait();
                Console.WriteLine(task.Result);
            }
            catch (Exception e)
            {
                Exception e2 = e.GetBaseException();
                System.Console.WriteLine(e2.Message);
            }

            Console.ReadKey();
        }
    }
}

証明書の検証を無効化する

handlerに以下を加える。

handler.ServerCertificateCustomValidationCallback =
    (message, cert, chain, errors) => { return true; };

補足: この設定は中間者攻撃を素通しにするため、 開発・デバッグ環境限定。本番コードに残さないこと。

ハンドラ委任について

HttpClientには、ハンドラ委任と言う概念がある。

参考

旧式のクラス

WebClientクラス

  • .NETでHTTPリクエストを処理するための最古のAPI。
  • 内部では、WebRequest, WebResponseクラスが利用される。
  • 参考

WebRequest, WebResponseクラス

Silverlight が SOAP サーバーと通信するケースが増えたため、追加されたAPI。

  • WebClientとの違いは、
    • WebRequest, WebResponseの2クラスに分割され、非同期対応がなされた。
    • WebRequest を使用して Request を送信し、Callback で WebResponse を取得する。
  • 各クラスには以下の派生クラスがある。
    • HttpWebRequest、FileWebRequest、FtpWebRequest
    • HttpWebResponse、FileWebResponse、FtpWebResponse
  • .NET Core の HttpWebRequest については、
    内部的にHttpClientクラスを new してアクセスしているらしい。

移行メモ(正誤): 原文は「WebResponseを使用してRequestを送信し、 CallbackでWebResponseを取得する」となっていたが、 Request を送信するのは WebRequest

補足(最新化): WebClient / WebRequest / HttpWebRequest はいずれも Obsolete 属性が付与された非推奨 API(.NET 6 以降)。 新規実装では HttpClient を使う。

参考

障害処理ポリシー


Tags: プログラミング, 通信技術, .NET開発, .NET Core, ASP.NET, ASP.NET Web API

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONETODO

Clone this wiki locally