Httpクライアント

重要な API

HttpClient と、Windows.Web.Http 名前空間 API の残りを使用して、HTTP 2.0 および HTTP 1.1 プロトコルを使用して情報を送受信します。

Tip

.NET 6 以降を対象とする WinUI 3 アプリでは、System.Net.Http.HttpClient (.NET HttpClient) も使用できます。 IHttpClientFactory、キャンセル トークン、最新の非同期パターンがサポートされています。 資格情報プロンプト、WinRT ブローカーによる Cookie 管理、Windows ネットワーク分離との統合など、WinRT 固有の機能が必要な場合は、Windows.Web.Http.HttpClientを使用します。 .NET WinUI 3 アプリでの単純な HTTP 要求の場合、多くの場合、System.Net.Http.HttpClientは簡単です。

HttpClient と Windows.Web.Http 名前空間の概要

Windows内のクラス。Web.Http 名前空間と関連するWindows。Web.Http.HeadersWindows。Web.Http.Filters 名前空間は、基本的な GET 要求を実行したり、以下に示すより高度な HTTP 機能を実装したりするための HTTP クライアントとして機能するWindows アプリのプログラミング インターフェイスを提供します。

  • 一般的な動詞 (DELETEGETPUTPOST) のメソッド。 これらの各要求は非同期操作として送信されます。

  • 一般的な認証設定とパターンのサポート。

  • トランスポートに関する Secure Sockets Layer (SSL) の詳細へのアクセス。

  • 高度なアプリにカスタマイズされたフィルターを含める機能。

  • Cookie を取得、設定、削除する機能。

  • 非同期メソッドで使用できる HTTP 要求の進行状況情報。

Windows.Web.Http.HttpRequestMessage クラスは、Windows.Web.Http.HttpClient によって送信される HTTP 要求メッセージを表します。 Windows。Web.Http.HttpResponseMessage クラスは、HTTP 要求から受信した HTTP 応答メッセージを表します。 HTTP メッセージは、IETF によって RFC 2616 で定義されています。

Windows。Web.Http 名前空間は、HTTP エンティティ本文として HTTP コンテンツを表し、Cookie を含むヘッダーを表します。 HTTP コンテンツは、HTTP 要求または HTTP 応答に関連付けることができます。 Windows。Web.Http 名前空間には、HTTP コンテンツを表すさまざまなクラスが用意されています。

  • HttpBufferContent。 バッファーとしてのコンテンツ
  • HttpFormUrlEncodedContentapplication/x-www-form-urlencoded MIME タイプでエンコードされた名前と値のタプルとしてのコンテンツ
  • HttpMultipartContentマルチパート/* MIME タイプの形式のコンテンツ。
  • HttpMultipartFormDataContentマルチパート/フォーム データ MIME タイプとしてエンコードされたコンテンツ。
  • HttpStreamContent。 ストリームとしてのコンテンツ (内部型は、データを受信するために HTTP GET メソッドによって使用され、データをアップロードする HTTP POST メソッドによって使用されます)
  • HttpStringContent。 文字列としてのコンテンツ。
  • IHttpContent - 開発者が独自のコンテンツ オブジェクトを作成するための基本インターフェイス

「HTTP 経由で単純な GET 要求を送信する」セクションのコード スニペットでは、 HttpStringContent クラスを使用して、HTTP GET 要求からの HTTP 応答を文字列として表します。

Windows。Web.Http.Headers 名前空間では、HTTP ヘッダーと Cookie の作成がサポートされ、HttpRequestMessage オブジェクトと HttpResponseMessage オブジェクトにプロパティとして関連付けられます。

HTTP 経由で単純な GET 要求を送信する

この記事で前述したように、Windows。Web.Http 名前空間を使用すると、Windows アプリで GET 要求を送信できます。 次のコード スニペットは、Windows.Web.Http.HttpClient クラスを使用して http://www.contoso.com に GET 要求を送信し、Windows.Web.Http.HttpResponseMessage クラスを使用して GET 要求に対する応答を読み取る方法を示しています。

//Create an HTTP client object
Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();

//Add a user-agent header to the GET request.
var headers = httpClient.DefaultRequestHeaders;

//The safe way to add a header value is to use the TryParseAdd method and verify the return value is true,
//especially if the header value is coming from user input.
string header = "MyApp/1.0";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

Uri requestUri = new Uri("http://www.contoso.com");

//Send the GET request asynchronously and retrieve the response as a string.
Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
string httpResponseBody = "";

try
{
    //Send the GET request
    httpResponse = await httpClient.GetAsync(requestUri);
    httpResponse.EnsureSuccessStatusCode();
    httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
    httpResponseBody = "Error: " + ex.HResult.ToString("X") + " Message: " + ex.Message;
}
// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
using namespace winrt;
using namespace Windows::Foundation;

int main()
{
    init_apartment();

    // Create an HttpClient object.
    Windows::Web::Http::HttpClient httpClient;

    // Add a user-agent header to the GET request.
    auto headers{ httpClient.DefaultRequestHeaders() };

    // The safe way to add a header value is to use the TryParseAdd method, and verify the return value is true.
    // This is especially important if the header value is coming from user input.
    std::wstring header{ L"MyApp/1.0" };
    if (!headers.UserAgent().TryParseAdd(header))
    {
        throw L"Invalid header value: " + header;
    }

    Uri requestUri{ L"http://www.contoso.com" };

    // Send the GET request asynchronously, and retrieve the response as a string.
    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Send the GET request.
        httpResponseMessage = httpClient.GetAsync(requestUri).get();
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
    }
    catch (winrt::hresult_error const& ex)
    {
        httpResponseBody = ex.message();
    }
    std::wcout << httpResponseBody;
}

HTTP 経由でバイナリ データを POST する

の C++/WinRT コード例は、フォーム データと POST 要求を使用して、少量のバイナリ データをファイルのアップロードとして Web サーバーに送信する方法を示しています。 このコードでは 、HttpBufferContent クラスを使用してバイナリ データを表し、 HttpMultipartFormDataContent クラスを使用してマルチパート フォーム データを表します。

Note

(次のコード例に示すように) get を呼び出すことは、UI スレッドには適していません。 その場合に使用する正しい手法については、「 C++/WinRT を使用したコンカレンシーと非同期操作」を参照してください。

// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Cryptography.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;

int main()
{
    init_apartment();

    auto buffer{
        Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary(
            L"A sentence of text to encode into binary to serve as sample data.",
            Windows::Security::Cryptography::BinaryStringEncoding::Utf8
        )
    };
    Windows::Web::Http::HttpBufferContent binaryContent{ buffer };
    // You can use the 'image/jpeg' content type to represent any binary data;
    // it's not necessarily an image file.
    binaryContent.Headers().Append(L"Content-Type", L"image/jpeg");

    Windows::Web::Http::Headers::HttpContentDispositionHeaderValue disposition{ L"form-data" };
    binaryContent.Headers().ContentDisposition(disposition);
    // The 'name' directive contains the name of the form field representing the data.
    disposition.Name(L"fileForUpload");
    // Here, the 'filename' directive is used to indicate to the server a file name
    // to use to save the uploaded data.
    disposition.FileName(L"file.dat");

    Windows::Web::Http::HttpMultipartFormDataContent postContent;
    postContent.Add(binaryContent); // Add the binary data content as a part of the form data content.

    // Send the POST request asynchronously, and retrieve the response as a string.
    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Send the POST request.
        Uri requestUri{ L"https://www.contoso.com/post" };
        Windows::Web::Http::HttpClient httpClient;
        httpResponseMessage = httpClient.PostAsync(requestUri, postContent).get();
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
    }
    catch (winrt::hresult_error const& ex)
    {
        httpResponseBody = ex.message();
    }
    std::wcout << httpResponseBody;
}

(上記で使用した明示的なバイナリ データではなく) 実際のバイナリ ファイルの内容を POST するには、 HttpStreamContent オブジェクトを使用する方が簡単です。 1 つを構築し、そのコンストラクターへの引数として、 StorageFile.OpenReadAsync への呼び出しから返された値を渡します。 そのメソッドは、バイナリ ファイル内のデータのストリームを返します。

また、大きなファイル (約 10 MB を超える) をアップロードする場合は、Windows ランタイムバックグラウンド転送 API を使用することをお勧めします。

HTTP 経由で JSON データを POST する

次の例では、いくつかの JSON をエンドポイントにポストし、応答本文を書き出します。

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Web.Http;

private async Task TryPostJsonAsync()
{
    try
    {
        // Construct the HttpClient and Uri. This endpoint is for test purposes only.
        HttpClient httpClient = new HttpClient();
        Uri uri = new Uri("https://www.contoso.com/post");

        // Construct the JSON to post.
        HttpStringContent content = new HttpStringContent(
            "{ \"firstName\": \"Eliot\" }",
            UnicodeEncoding.Utf8,
            "application/json");

        // Post the JSON and wait for a response.
        HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(
            uri,
            content);

        // Make sure the post succeeded, and write out the response.
        httpResponseMessage.EnsureSuccessStatusCode();
        var httpResponseBody = await httpResponseMessage.Content.ReadAsStringAsync();
        Debug.WriteLine(httpResponseBody);
    }
    catch (Exception ex)
    {
        // Write out any exceptions.
        Debug.WriteLine(ex);
    }
}
// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Cryptography.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;

int main()
{
    init_apartment();

    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Construct the HttpClient and Uri. This endpoint is for test purposes only.
        Windows::Web::Http::HttpClient httpClient;
        Uri requestUri{ L"https://www.contoso.com/post" };

        // Construct the JSON to post.
        Windows::Web::Http::HttpStringContent jsonContent(
            L"{ \"firstName\": \"Eliot\" }",
            UnicodeEncoding::Utf8,
            L"application/json");

        // Post the JSON, and wait for a response.
        httpResponseMessage = httpClient.PostAsync(
            requestUri,
            jsonContent).get();

        // Make sure the post succeeded, and write out the response.
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
        std::wcout << httpResponseBody.c_str();
    }
    catch (winrt::hresult_error const& ex)
    {
        std::wcout << ex.message().c_str();
    }
}

Windows.Web.Http の例外

Uniform Resource Identifier (URI) として無効な文字列が Windows.Foundation.Uri オブジェクトのコンストラクターに渡されると、例外がスローされます。

.NET:Windows。Foundation.Uri 型は、C# および VB で System.Uri として表示されます。

C# および Visual Basic では、このエラーは、.NET 4.5 の System.Uri クラスと System.Uri.TryCreate メソッドの 1 つを使用して、URI が構築される前にユーザーから受信した文字列をテストすることで回避できます。

C++ では、文字列を URI に解析しようとするメソッドはありません。 アプリが Windows.Foundation.Uri を生成するための入力をユーザーから受け取る場合、コンストラクターの呼び出しは try/catch ブロックで囲む必要があります。 例外が発生した場合、アプリはユーザーに通知し、新しいホスト名の入力を求めることができます。

Windows。Web.Http には便利な関数がありません。 そのため、 HttpClient とこの名前空間の他のクラスを使用するアプリでは、 HRESULT 値を使用する必要があります。

C++/WinRT を使用するアプリでは、winrt::hresult_error 構造体はアプリの実行中に発生する例外を表します。 winrt::hresult_error::code 関数は、特定の例外に割り当てられた HRESULT を返します。 winrt::hresult_error::message 関数は、HRESULT 値に関連付けられているシステム指定の文字列を返します。 詳細については、「C++/WinRT でのエラー処理」を参照してください。

使用可能な HRESULT 値は、 Winerror.h ヘッダー ファイルに一覧表示されます。 アプリでは、特定の HRESULT 値をフィルター処理して、例外の原因に応じてアプリの動作を変更できます。

C#、VB.NET で .NET Framework 4.5 を使用するアプリでは、System.Exception は、例外が発生したときにアプリの実行中にエラーを表します。 System.Exception.HResult プロパティは、特定の例外に割り当てられた HRESULT を返します。 System.Exception.Message プロパティは、例外を説明するメッセージを返します。

C++/CX は C++/WinRT に置き換わりました。 ただし、C++/CX を使用するアプリでは、 Platform::Exception は例外 が発生したときにアプリの実行中にエラーを表します。 Platform::Exception::HResult プロパティは、特定の例外に割り当てられた HRESULT を返します。 Platform::Exception::Message プロパティは、HRESULT 値に関連付けられているシステム指定の文字列を返します。

ほとんどのパラメーター検証エラーでは、返される HRESULTE_INVALIDARG。 一部の無効なメソッド呼び出しの場合、返される HRESULTE_ILLEGAL_METHOD_CALL