Cliente HTTP

APIs importantes

Use o HttpClient e o restante da API do namespace Windows.Web.Http para enviar e receber informações usando os protocolos HTTP 2.0 e HTTP 1.1.

Tip

Aplicativos WinUI 3 destinados ao .NET 6 ou posterior também podem usar System.Net.Http.HttpClient (o .NET HttpClient). Ele suporta IHttpClientFactory, tokens de cancelamento e padrões assíncronos modernos. Use o Windows.Web.Http.HttpClient quando precisar de recursos específicos do WinRT, como solicitações de credenciais, gerenciamento de cookies por meio do broker do WinRT ou integração com o isolamento de rede do Windows. Para solicitações HTTP simples em um aplicativo WinUI 3 .NET, geralmente é System.Net.Http.HttpClient mais simples.

Visão geral do HttpClient e do namespace Windows.Web.Http

As classes no namespace Windows.Web.Http e nos namespaces relacionados Windows.Web.Http.Headers e Windows.Web.Http.Filters fornecem uma interface de programação para aplicativos do Windows que atuam como clientes HTTP para executar solicitações GET básicas ou implementar funcionalidades HTTP mais avançadas listadas a seguir.

  • Métodos para verbos comuns (DELETE, GET, PUT e POST). Cada uma dessas solicitações é enviada como uma operação assíncrona.

  • Suporte para padrões e configurações de autenticação comuns.

  • Acesso aos detalhes da SSL (Secure Sockets Layer) no transporte.

  • Capacidade de incluir filtros personalizados em aplicativos avançados.

  • Capacidade de obter, definir e excluir cookies.

  • Informações de progresso da solicitação HTTP disponíveis em métodos assíncronos.

A classe Windows.Web.Http.HttpRequestMessage representa uma mensagem de solicitação HTTP enviada por Windows.Web.Http.HttpClient. A classe Windows.Web.Http.HttpResponseMessage representa uma mensagem de resposta HTTP recebida em uma solicitação HTTP. As mensagens HTTP são definidas no RFC 2616 pelo IETF.

O namespace Windows.Web.Http representa o conteúdo HTTP na forma de corpo e cabeçalhos da entidade HTTP, incluindo cookies. O conteúdo HTTP pode ser associado a uma solicitação HTTP ou a uma resposta HTTP. O namespace Windows.Web.Http fornece várias classes diferentes para representar o conteúdo HTTP.

O snippet de código na seção "Enviar uma solicitação GET simples por HTTP" usa a classe HttpStringContent para representar a resposta HTTP de uma solicitação HTTP GET como uma cadeia de caracteres.

O namespace Windows.Web.Http.Headers dá suporte à criação de cabeçalhos HTTP e cookies, que são então associados como propriedades aos objetos HttpRequestMessage e HttpResponseMessage.

Enviar uma solicitação GET simples por HTTP

Conforme mencionado anteriormente neste artigo, o namespace Windows.Web.Http permite que aplicativos do Windows enviem solicitações GET. O snippet de código a seguir demonstra como enviar uma solicitação GET para http://www.contoso.com usar o Windows. Classe Web.Http.HttpClient e a Windows. Classe Web.Http.HttpResponseMessage para ler a resposta da solicitação 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;
}

Enviar dados binários via HTTP

O exemplo de código C++/WinRT abaixo ilustra o uso de dados de formulário e uma solicitação POST para enviar uma pequena quantidade de dados binários como um upload de arquivo para um servidor Web. O código usa a classe HttpBufferContent para representar os dados binários e a classe HttpMultipartFormDataContent para representar os dados de formulário de várias partes.

Note

Chamar get (como visto no exemplo de código abaixo) não é apropriado para um thread de interface do usuário. Para obter a técnica correta a ser usada nesse caso, consulte Simultaneidade e operações assíncronas com 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;
}

Para POSTAR o conteúdo de um arquivo binário real (em vez dos dados binários explícitos usados acima), você achará mais fácil usar um objeto HttpStreamContent . Construa um e, como o argumento para seu construtor, passe o valor retornado de uma chamada para StorageFile.OpenReadAsync. Esse método retorna um fluxo para os dados dentro do arquivo binário.

Além disso, se você estiver carregando um arquivo grande (maior que cerca de 10 MB), recomendamos que você use as APIs de Transferência em Segundo Plano Windows Runtime.

POSTAR dados JSON por HTTP

O exemplo a seguir envia um JSON para um endpoint e, em seguida, exibe o corpo da resposta.

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

Exceções em Windows. Web.Http

Uma exceção é gerada quando uma cadeia de caracteres inválida para um URI (Uniform Resource Identifier) é passada para o construtor do Windows. Objeto Foundation.Uri.

.NET: O tipo Windows.Foundation.Uri aparece como System.Uri em C# e VB.

Em C# e Visual Basic, esse erro pode ser evitado usando a classe System.Uri no .NET 4.5 e um dos métodos System.Uri.TryCreate para testar a cadeia de caracteres recebida de um usuário antes que o URI seja construído.

No C++, não há nenhum método para tentar analisar uma cadeia de caracteres para um URI. Se um aplicativo receber entrada do usuário para criar o Windows.Foundation.Uri, o construtor deverá ficar dentro de um bloco try/catch. Se uma exceção for gerada, o aplicativo poderá notificar o usuário e solicitar um novo nome de host.

O Windows. Web.Http não tem uma função de conveniência. Portanto, um aplicativo que usa HttpClient e outras classes nesse namespace precisa usar o valor HRESULT .

Em aplicativos que usam C++/WinRT, o struct winrt::hresult_error representa uma exceção gerada durante a execução do aplicativo. A função winrt::hresult_error::code retorna o HRESULT atribuído à exceção específica. A função winrt::hresult_error::message retorna a cadeia de caracteres fornecida pelo sistema associada ao valor HRESULT . Para obter mais informações, consulte Tratamento de erros com C++/WinRT

Possíveis valores HRESULT são listados no arquivo de cabeçalho Winerror.h . Seu aplicativo pode filtrar valores HRESULT específicos para modificar o comportamento do aplicativo, dependendo da causa da exceção.

Em aplicativos que usam o .NET Framework 4.5 em C#, VB.NET, o System.Exception representa um erro durante a execução do aplicativo quando ocorre uma exceção. A propriedade System.Exception.HResult retorna o HRESULT atribuído à exceção específica. A propriedade System.Exception.Message retorna a mensagem que descreve a exceção.

C++/CX foi substituído por C++/WinRT. Mas em aplicativos que usam C++/CX, a Plataforma::Exceção representa um erro durante a execução do aplicativo quando ocorre uma exceção. A propriedade Platform::Exception::HResult retorna o HRESULT atribuído à exceção específica. A propriedade Platform::Exception::Message retorna a cadeia de caracteres fornecida pelo sistema associada ao valor HRESULT .

Para a maioria dos erros de validação de parâmetro, o HRESULT retornado é E_INVALIDARG. Para algumas chamadas de método ilegais, o HRESULT retornado é E_ILLEGAL_METHOD_CALL.