HttpClient

重要 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 專屬功能,例如憑證提示、透過 WinRT 代理管理 Cookie,或與 Windows 網路隔離整合時,請使用此Windows.Web.Http.HttpClient方法。 對於 .NET WinUI 3 應用程式中的直接 HTTP 請求,System.Net.Http.HttpClient通常會比較簡單。

HttpClient 與 Windows.Web.Http 命名空間的概觀

Windows 裡的類別。Web.Http 命名空間及相關 Windows。Web.Http.標頭Windows。Web.Http.Filters 命名空間為 Windows 應用程式提供程式介面,這些應用程式作為 HTTP 用戶端,執行基本的 GET 請求或實作下方列出的更進階 HTTP 功能。

  • 常見動詞的方法(DELETE、GETPUTPOST)。 這些請求都是以非同步操作方式發送。

  • 支援通用的認證設定與模式。

  • 對傳輸層上的安全通訊端層(SSL)詳細資料的存取。

  • 能在進階應用程式中加入自訂篩選功能。

  • 能夠取得、設定及刪除 Cookie。

  • HTTP 請求進度資訊可透過非同步方法取得。

Windows。Web.Http.HttpRequestMessage 類別代表 Windows 發送的 HTTP 請求訊息。Web.Http.HttpClient Windows。Web.Http.HttpResponseMessage 類別代表從 HTTP 請求中接收到的 HTTP 回應訊息。 HTTP 訊息由 IETF 在 RFC 2616 中定義。

Windows。Web.Http 命名空間將 HTTP 內容作為 HTTP 實體主體及標頭(包括 Cookies)來表示。 HTTP 內容可以與 HTTP 請求或 HTTP 回應相關聯。 Windows。Web.Http 命名空間提供多種不同的類別來表示 HTTP 內容。

「透過 HTTP 發送簡單 GET 請求」部分的程式碼片段使用 HttpStringContent 類別,將 HTTP GET 請求的 HTTP 回應表示為字串。

Windows。Web.Http.Headers 命名空間支援建立 HTTP 標頭與 Cookie,這些 Cookie 會作為屬性與 HttpRequestMessageHttpResponseMessage 物件關聯。

透過 HTTP 發送一個簡單的 GET 請求

如本文先前提到的,Windows。Web.Http 命名空間允許 Windows 應用程式發送 GET 請求。 以下程式碼片段示範如何使用 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("https://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"https://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 請求,將少量二進位資料以檔案上傳方式上傳至網頁伺服器。 程式碼使用 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;
}

要發佈實際二進位檔案的內容(而非上述明確的二進位資料),你會發現使用 HttpStreamContent 物件會比較簡單。 建構一個物件,並將呼叫 StorageFile.OpenReadAsync 所傳回的值作為引數傳遞給其建構函式。 這個方法會回傳你二進位檔案中的資料串流。

另外,如果你上傳的是大型檔案(大於約 10MB),我們建議你使用 Windows 執行階段 背景傳輸 API。

透過 HTTP 發佈 JSON 資料

以下範例會將一些 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 中的例外

當無效的統一資源識別項 (URI) 字串傳遞至 Windows.Foundation.Uri 物件的建構函式時,會擲回例外狀況。

.NET:Windows。Foundation.Uri 型態在 C# 和 VB 中以 System.Uri 形式出現。

在 C# 和 Visual Basic 中,可以透過使用 .NET 4.5 中的 System.Uri 類別以及 System.Uri.TryCreate 方法來測試使用者在建構 URI 前收到的字串來避免此錯誤。

在 C++ 中,沒有方法可以嘗試解析字串成 URI。 如果應用程式從使用者取得 Windows.Foundation.Uri 的輸入,則建構函式應置於 try/catch 區塊中。 若拋出例外,應用程式可通知使用者並請求更換主機名稱。

Windows。Web.Http 缺乏便利功能。 因此,使用 HttpClient 及其他類別的應用程式必須使用 HRESULT 值。

在使用 C++/WinRT 的應用程式中, winrt::hresult_error 結構代表應用程式執行時提出的例外。 winrt:hresult_error:code 函式會回傳指派給特定例外的 HRESULTwinrt:hresult_error:message 函式會回傳與 HRESULT 值相關聯的系統提供的字串。 更多資訊請參閱 C++/WinRT 的錯誤處理

可能的 HRESULT 值列於 Winerror.h 標頭檔案中。 你的應用程式可以根據異常原因,針對特定的 HRESULT 值進行篩選,修改應用程式行為。

在使用 C#、VB.NET .NET Framework 4.5 的應用程式中,System.Exception 代表應用程式執行中發生異常時的錯誤。 System.Exception.HResult 屬性會回傳指派給該特定例外的 HRESULTSystem.Exception.Message 屬性會回傳描述該例外的訊息。

C++/CX 已被 C++/WinRT 取代。 但在使用 C++/CX 的應用程式中, Platform::Exception 代表應用程式執行時發生異常時的錯誤。 Platform::Exception::HResult 屬性會傳回指派給該特定例外的 HRESULTPlatform::Exception::Message 屬性會回傳系統提供的字串,該字串與 HRESULT 值相關聯。

對於大多數參數驗證錯誤,回傳的 HRESULTE_INVALIDARG。 對於某些非法方法呼叫,回傳的 HRESULTE_ILLEGAL_METHOD_CALL