HttpClient

ważne interfejsy API

Użyj HttpClient i pozostałych interfejsów API przestrzeni nazw Windows.Web.Http do wysyłania i odbierania informacji przy użyciu protokołów HTTP 2.0 i HTTP 1.1.

Tip

Aplikacje WinUI 3 przeznaczone dla .NET 6 lub nowszych mogą również używać System.Net.Http.HttpClient (.NET HttpClient). Obsługuje IHttpClientFactory, tokeny anulowania i nowoczesne wzorce async. Użyj Windows.Web.Http.HttpClient, gdy potrzebujesz funkcji specyficznych dla środowiska WinRT, takich jak monity o poświadczenia, zarządzanie plikami cookie za pośrednictwem brokera WinRT lub integracja z izolacją sieciową systemu Windows. W przypadku prostych żądań HTTP w aplikacji .NET WinUI 3 System.Net.Http.HttpClient jest często prostsze.

Omówienie klasy HttpClient i przestrzeni nazw Windows.Web.Http

Klasy w Windows. Przestrzeń nazw Web.Http i powiązane Windows. Web.Http.Headers i Windows. Przestrzenie nazw Web.Http.Filters udostępniają interfejs programowania dla aplikacji Windows, które działają jako klient HTTP w celu wykonywania podstawowych żądań GET lub implementowania bardziej zaawansowanych funkcji HTTP wymienionych poniżej.

  • Metody typowych czasowników (DELETE, GET, PUT i POST). Każde z tych żądań jest wysyłane jako operacja asynchroniczna.

  • Obsługa typowych ustawień i wzorców uwierzytelniania.

  • Dostęp do szczegółów protokołu SECURE Sockets Layer (SSL) dotyczących transportu.

  • Możliwość uwzględnienia dostosowanych filtrów w zaawansowanych aplikacjach.

  • Możliwość pobierania, ustawiania i usuwania plików cookie.

  • Informacje o postępie żądania HTTP dostępne w metodach asynchronicznych.

Klasa Windows.Web.Http.HttpRequestMessage reprezentuje komunikat żądania HTTP wysyłany przez Windows.Web.Http.HttpClient. Klasa Windows.Web.Http.HttpResponseMessage reprezentuje komunikat odpowiedzi HTTP otrzymany w wyniku żądania HTTP. Komunikaty HTTP są definiowane w dokumencie RFC 2616 przez IETF.

Przestrzeń nazw Windows.Web.Http reprezentuje zawartość HTTP w postaci treści jednostki i nagłówków HTTP, w tym plików cookie. Zawartość HTTP może być skojarzona z żądaniem HTTP lub odpowiedzią HTTP. Przestrzeń nazw Windows.Web.Http udostępnia wiele różnych klas służących do reprezentowania zawartości HTTP.

Fragment kodu w sekcji "Wyślij proste żądanie GET za pośrednictwem protokołu HTTP" używa klasy HttpStringContent do reprezentowania odpowiedzi HTTP z żądania HTTP GET jako ciągu.

Windows. Przestrzeń nazw Web.Http.Headers obsługuje tworzenie nagłówków HTTP i plików cookie, które są następnie skojarzone jako właściwości z obiektami HttpRequestMessage i HttpResponseMessage.

Wysyłanie prostego żądania GET za pośrednictwem protokołu HTTP

Jak wspomniano wcześniej w tym artykule, przestrzeń nazw Windows.Web.Http umożliwia aplikacjom systemu Windows wysyłanie żądań GET. Poniższy fragment kodu pokazuje, jak wysłać żądanie GET do http://www.contoso.com przy użyciu klasy Windows.Web.Http.HttpClient oraz klasy Windows.Web.Http.HttpResponseMessage w celu odczytania odpowiedzi na żądanie 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;
}

Prześlij dane binarne metodą POST przez HTTP

Poniższy przykład kodu C++/WinRT ilustruje użycie danych formularza i żądania POST w celu wysłania niewielkiej ilości danych binarnych jako pliku przekazanego do serwera internetowego. Kod używa klasy HttpBufferContent do reprezentowania danych binarnych, a klasa HttpMultipartFormDataContent reprezentuje dane formularza wieloczęściowego.

Note

Wywołanie get (jak pokazano w poniższym przykładzie kodu) nie jest odpowiednie w wątku interfejsu użytkownika. Aby uzyskać poprawną technikę do użycia w tym przypadku, zobacz Współbieżność i operacje asynchroniczne z językiem 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;
}

Aby opublikować zawartość rzeczywistego pliku binarnego (zamiast jawnych danych binarnych użytych powyżej), łatwiej będzie użyć obiektu HttpStreamContent . Utwórz obiekt i jako argument konstruktora przekaż wartość zwróconą przez wywołanie metody StorageFile.OpenReadAsync. Ta metoda zwraca strumień danych wewnątrz pliku binarnego.

Ponadto, jeśli przesyłasz duży plik (większy niż około 10 MB), zalecamy użycie interfejsów API Background Transfer środowiska środowisko wykonawcze systemu Windows.

Prześlij dane JSON przez HTTP

Poniższy przykład publikuje niektóre dane JSON w punkcie końcowym, a następnie zapisuje treść odpowiedzi.

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();
    }
}

Wyjątki w Windows. Web.Http

Wyjątek jest zgłaszany, gdy do konstruktora obiektu Windows.Foundation.Uri zostanie przekazany nieprawidłowy ciąg znaków dla identyfikatora URI (Uniform Resource Identifier).

.NET: Typ Windows.Foundation.Uri jest przedstawiany jako System.Uri w językach C# i VB.

W językach C# i Visual Basic ten błąd można uniknąć przy użyciu klasy System.Uri w .NET 4.5 i jednej z metod System.Uri.TryCreate w celu przetestowania ciągu otrzymanego od użytkownika przed skonstruowaniem identyfikatora URI.

W języku C++ nie ma metody umożliwiającej próbę przekształcenia ciągu znaków na identyfikator URI. Jeśli aplikacja pobiera dane wejściowe od użytkownika dla Windows. Foundation.Uri konstruktor powinien znajdować się w bloku try/catch. Jeśli zostanie zgłoszony wyjątek, aplikacja może powiadomić użytkownika i zażądać nowej nazwy hosta.

Windows. Web.Http nie ma funkcji wygody. Dlatego aplikacja korzystająca z klasy HttpClient i innych klas w tej przestrzeni nazw musi używać wartości HRESULT .

W aplikacjach korzystających z języka C++/WinRT struktura winrt::hresult_error reprezentuje wyjątek zgłoszony podczas wykonywania aplikacji. Funkcja winrt::hresult_error::code zwraca wartość HRESULT przypisaną do określonego wyjątku. Funkcja winrt::hresult_error::message zwraca ciąg dostarczony przez system skojarzony z wartością HRESULT . Aby uzyskać więcej informacji, zobacz Obsługa błędów w języku C++/WinRT

Możliwe wartości HRESULT są wymienione w pliku nagłówka Winerror.h . Aplikacja może filtrować określone wartości HRESULT , aby zmodyfikować zachowanie aplikacji w zależności od przyczyny wyjątku.

W aplikacjach korzystających z platformy .NET Framework 4.5 w języku C#, VB.NET wyjątek System.Exception reprezentuje błąd podczas wykonywania aplikacji, gdy wystąpi wyjątek. Właściwość System.Exception.HResult zwraca właściwość HRESULT przypisaną do określonego wyjątku. Właściwość System.Exception.Message zwraca komunikat opisujący wyjątek.

Język C++/CX został zastąpiony przez język C++/WinRT. Jednak w aplikacjach korzystających z języka C++/CX wyjątek Platform::Exception reprezentuje błąd podczas wykonywania aplikacji, gdy wystąpi wyjątek. Właściwość Platform::Exception::HResult zwraca właściwość HRESULT przypisaną do określonego wyjątku. Właściwość Platform::Exception::Message zwraca ciąg dostarczony przez system skojarzony z wartością HRESULT .

W przypadku większości błędów sprawdzania poprawności parametrów zwracanym kodem jest HRESULTE_INVALIDARG. W przypadku niektórych niedozwolonych wywołań metod zwracana jest wartość HRESULTE_ILLEGAL_METHOD_CALL.