Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
API importantes
Utilisez HttpClient et le reste de la Windows. API d’espace de noms Web.Http pour envoyer et recevoir des informations à l’aide des protocoles HTTP 2.0 et HTTP 1.1.
Conseil
Les applications WinUI 3 ciblant .NET 6 ou version ultérieure peuvent également utiliser System.Net.Http.HttpClient (le HttpClient .NET). Il prend en charge IHttpClientFactory, les jetons d’annulation et les modèles asynchrones modernes. Utilisez Windows.Web.Http.HttpClient lorsque vous avez besoin de fonctionnalités spécifiques à WinRT, telles que les demandes d’informations d’identification, la gestion des cookies via le broker WinRT ou l’intégration à l’isolation réseau de Windows. Pour les requêtes HTTP simples dans une application .NET WinUI 3, System.Net.Http.HttpClient est souvent plus simple.
Vue d’ensemble de HttpClient et de l’espace de noms Windows.Web.Http
Les classes de l’espace de noms Windows.Web.Http ainsi que des espaces de noms connexes Windows.Web.Http.Headers et Windows.Web.Http.Filters fournissent une interface de programmation pour les applications Windows qui agissent comme clients HTTP afin d’effectuer des requêtes GET de base ou d’implémenter des fonctionnalités HTTP plus avancées décrites ci-dessous.
Méthodes pour les verbes courants (DELETE, GET, PUT et POST). Chacune de ces demandes est envoyée en tant qu’opération asynchrone.
Prise en charge des paramètres et modèles d’authentification courants.
Accès aux détails SSL (Secure Sockets Layer) sur le transport.
Possibilité d’inclure des filtres personnalisés dans des applications avancées.
Possibilité d’obtenir, de définir et de supprimer des cookies.
Informations de progression de la requête HTTP disponibles sur les méthodes asynchrones.
La classe Windows.Web.Http.HttpRequestMessage représente un message de requête HTTP envoyé par Windows.Web.Http.HttpClient. La classe Windows.Web.Http.HttpResponseMessage représente un message de réponse HTTP reçu en réponse à une requête HTTP. Les messages HTTP sont définis dans RFC 2616 par l’IETF.
L’espace de noms Windows.Web.Http représente le contenu HTTP sous forme de corps et d’en-têtes d’entité HTTP, y compris les cookies. Le contenu HTTP peut être associé à une requête HTTP ou à une réponse HTTP. L’espace de noms Windows.Web.Http fournit différentes classes pour représenter du contenu HTTP.
- HttpBufferContent. Contenu en tant que mémoire tampon
- HttpFormUrlEncodedContent. Contenu en tant que nom et tuples de valeur encodés avec le type MIME application/x-www-form-urlencoded
- HttpMultipartContent. Contenu sous la forme du type MIME multipart/* .
- HttpMultipartFormDataContent. Contenu encodé en tant que type MIME multipart/form-data .
- HttpStreamContent. Contenu en tant que flux (le type interne est utilisé par la méthode HTTP GET pour recevoir des données et la méthode HTTP POST pour charger des données)
- HttpStringContent. Contenu sous forme de chaîne.
- IHttpContent : interface de base permettant aux développeurs de créer leurs propres objets de contenu
L’extrait de code de la section « Envoyer une requête GET simple sur HTTP » utilise la classe HttpStringContent pour représenter la réponse HTTP à partir d’une requête HTTP GET sous forme de chaîne.
L’espace de noms Windows.Web.Http.Headers prend en charge la création d’en-têtes HTTP et de cookies, qui sont ensuite associés comme propriétés des objets HttpRequestMessage et HttpResponseMessage.
Envoyer une requête GET simple via HTTP
Comme mentionné précédemment dans cet article, le Windows. L’espace de noms Web.Http permet aux applications Windows d’envoyer des requêtes GET. L’extrait de code suivant montre comment envoyer une requête GET à http://www.contoso.com l’aide du Windows. Classe Web.Http.HttpClient et Windows. Classe Web.Http.HttpResponseMessage pour lire la réponse de la requête 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;
}
Envoyer des données binaires via HTTP
L’exemple de code C++/WinRT ci-dessous illustre l’utilisation de données de formulaire et d’une requête POST pour envoyer une petite quantité de données binaires en tant que chargement de fichier sur un serveur web. Le code utilise la classe HttpBufferContent pour représenter les données binaires et la classe HttpMultipartFormDataContent pour représenter les données de formulaire en plusieurs parties.
Note
L’appel à get (comme indiqué dans l’exemple de code ci-dessous) n’est pas approprié dans un thread d’interface utilisateur. Pour connaître la technique correcte à utiliser dans ce cas, consultez Concurrence et opérations asynchrones avec 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;
}
Pour PUBLIER le contenu d’un fichier binaire réel (plutôt que les données binaires explicites utilisées ci-dessus), vous trouverez plus facile d’utiliser un objet HttpStreamContent . Construisez-en un et, en tant qu’argument à son constructeur, transmettez la valeur retournée à partir d’un appel à StorageFile.OpenReadAsync. Cette méthode retourne un flux pour les données à l’intérieur de votre fichier binaire.
En outre, si vous chargez un fichier volumineux (supérieur à environ 10 Mo), nous vous recommandons d'utiliser les API de transfert en arrière-plan Windows Runtime.
Envoyer des données JSON par requête POST HTTP
L’exemple suivant publie un code JSON sur un point de terminaison, puis écrit le corps de la réponse.
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();
}
}
Gérer les erreurs
Un appel effectué avec HttpClient peut échouer de deux façons distinctes, et vous gérez chacun d’eux différemment.
- Le serveur répond avec un code d’état d’erreur. La requête se termine, mais le serveur retourne un code d’état 4xx ou 5xx (par exemple, 404 Introuvable ou 503 Service indisponible). Cela ne lève pas d’exception. L’appel à
GetAsyncou àPostAsyncrenvoie normalement une valeur de type HttpResponseMessage dont la propriété IsSuccessStatusCode estfalse. - La demande échoue avant la réception d’une réponse. Le client ne peut pas terminer l’échange du tout (par exemple, il n’existe aucune connexion réseau, le nom d’hôte ne résout pas, la connexion expire ou la négociation TLS échoue). Cela lève une exception.
Comme un code d’erreur renvoyé ne génère pas d’exception, il ne suffit pas de vérifier uniquement les exceptions. Inspectez la réponse et interceptez les exceptions.
Vérifier le code d’état de la réponse
Lisez HttpResponseMessage.IsSuccessStatusCode pour tester si le serveur a retourné un code de réussite (2xx). Pour effectuer un branchement en fonction du code d’état précis, lisez HttpResponseMessage.StatusCode (une valeur HttpStatusCode) et ReasonPhrase.
L’appel de EnsureSuccessStatusCode, comme les exemples précédents, est un raccourci qui lève une exception lorsque le code d’état n’est pas un code de réussite. Vous pouvez donc gérer les deux modes d’échec dans un seul catch bloc. Appelez-le uniquement lorsque vous souhaitez qu’un code non réussi soit traité comme une erreur. Si vous souhaitez lire le corps d’une réponse 4xx ou 5xx, consultez plutôt IsSuccessStatusCode.
Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();
Uri requestUri = new Uri("https://www.contoso.com");
Windows.Web.Http.HttpResponseMessage response = await httpClient.GetAsync(requestUri);
if (response.IsSuccessStatusCode)
{
string body = await response.Content.ReadAsStringAsync();
// Process the successful response.
}
else
{
// The server responded, but with an error status code.
System.Diagnostics.Debug.WriteLine($"Request failed: {(int)response.StatusCode} {response.StatusCode} ({response.ReasonPhrase})");
}
Classifier une exception réseau
Lorsqu’une requête déclenche une exception avant qu’une réponse ne soit reçue (par exemple, si le nom ne peut pas être résolu, ou si la connexion échoue ou dépasse le délai imparti), la valeur HResult de l’exception identifie l’erreur réseau sous-jacente. Passez-le à Windows. Web.WebError.GetStatus pour obtenir une valeur WebErrorStatus qui décrit la cause (par exemple, HostNameNotResolved, , CannotConnect, Timeoutou ConnectionReset). Utilisez-le pour décider s’il faut avertir l’utilisateur, revenir en arrière ou réessayer.
WebError.GetStatus ne s’applique pas aux réponses d’erreur HTTP (codes d’état 4xx ou 5xx), car le serveur a répondu. Vérifiez HttpResponseMessage.IsSuccessStatusCode ou HttpResponseMessage.StatusCode pour gérer ceux au lieu d’appeler EnsureSuccessStatusCode.
Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();
Uri requestUri = new Uri("https://www.contoso.com");
try
{
Windows.Web.Http.HttpResponseMessage response = await httpClient.GetAsync(requestUri);
if (!response.IsSuccessStatusCode)
{
// Handle the non-success HTTP status code (for example, 404 Not Found or 503 Service Unavailable).
System.Diagnostics.Debug.WriteLine($"HTTP error: {(int)response.StatusCode} {response.StatusCode}");
return;
}
string body = await response.Content.ReadAsStringAsync();
// Process the successful response.
}
catch (Exception ex)
{
Windows.Web.WebErrorStatus status = Windows.Web.WebError.GetStatus(ex.HResult);
switch (status)
{
case Windows.Web.WebErrorStatus.HostNameNotResolved:
case Windows.Web.WebErrorStatus.CannotConnect:
case Windows.Web.WebErrorStatus.Timeout:
case Windows.Web.WebErrorStatus.ConnectionReset:
// A transient connectivity problem. Retrying with backoff may succeed.
System.Diagnostics.Debug.WriteLine($"Network error: {status}.");
break;
case Windows.Web.WebErrorStatus.Unknown:
// GetStatus couldn't map the HRESULT to a WebErrorStatus value.
System.Diagnostics.Debug.WriteLine($"Unmapped error. HRESULT: 0x{ex.HResult:X8} {ex.Message}");
break;
default:
System.Diagnostics.Debug.WriteLine($"Web error: {status}");
break;
}
}
Le même modèle s’applique en C++/WinRT, à l’aide de winrt ::hresult_error ::code comme entrée à GetStatus.
// #include <winrt/Windows.Web.h>
try
{
auto response{ httpClient.GetAsync(requestUri).get() };
if (!response.IsSuccessStatusCode())
{
// Handle the non-success HTTP status code (for example, 404 Not Found or 503 Service Unavailable).
}
else
{
auto body{ response.Content().ReadAsStringAsync().get() };
// Process the successful response.
}
}
catch (winrt::hresult_error const& ex)
{
Windows::Web::WebErrorStatus status{ Windows::Web::WebError::GetStatus(ex.code()) };
if (status == Windows::Web::WebErrorStatus::HostNameNotResolved ||
status == Windows::Web::WebErrorStatus::CannotConnect ||
status == Windows::Web::WebErrorStatus::Timeout ||
status == Windows::Web::WebErrorStatus::ConnectionReset)
{
// A transient connectivity problem. Retrying with backoff may succeed.
}
else
{
// Inspect status, or fall back to ex.code() and ex.message().
}
}
Réessayer en cas d’échecs temporaires
HttpClient ne réessaye pas les demandes ayant échoué pour vous. Pour les échecs temporaires (erreurs de connectivité indiquées ci-dessus, ou codes de serveur tels que 429 Trop de requêtes, 503 Service indisponible et délai d’expiration de la passerelle 504), réessayez la demande vous-même à l’aide d’un retour exponentiel et respectez l’en-tête Retry-After de réponse lorsque le serveur en envoie un. Limitez le nombre de tentatives et n’effectuez pas de nouvelles tentatives d’erreurs non temporaires telles que la requête incorrecte 400 ou 404 introuvable.
Exceptions dans Windows. Web.Http
Une exception est levée lorsqu’une chaîne non valide pour un identificateur de ressource uniforme (URI) est passée au constructeur de l’objet Windows.Foundation.Uri.
.NET : Le type Windows.Foundation.Uri apparaît comme System.Uri en C# et VB.
En C# et Visual Basic, cette erreur peut être évitée à l’aide de la classe System.Uri dans la .NET 4.5 et l’une des méthodes System.Uri.TryCreate pour tester la chaîne reçue d’un utilisateur avant la construction de l’URI.
En C++, il n’existe aucune méthode pour essayer d’analyser une chaîne à un URI. Si une application obtient une entrée de l’utilisateur pour la classe Windows.Foundation.Uri, le constructeur doit se trouver dans un bloc try/catch. Si une exception est levée, l’application peut avertir l’utilisateur et demander un nouveau nom d’hôte.
Le Windows. Web.Http ne dispose pas d’une fonction pratique. Par conséquent, une application utilisant HttpClient et d’autres classes dans cet espace de noms doit utiliser la valeur HRESULT .
Dans les applications utilisant C++/WinRT, le struct winrt ::hresult_error représente une exception levée pendant l’exécution de l’application. La fonction winrt ::hresult_error ::code retourne le HRESULT affecté à l’exception spécifique. La fonction winrt ::hresult_error ::message retourne la chaîne fournie par le système associée à la valeur HRESULT . Pour plus d’informations, consultez Gestion des erreurs avec C++/WinRT
Les valeurs HRESULT possibles sont répertoriées dans le fichier d’en-tête Winerror.h . Votre application peut filtrer sur des valeurs HRESULT spécifiques pour modifier le comportement de l’application en fonction de la cause de l’exception.
Dans les applications utilisant le .NET Framework 4.5 en C#, VB.NET, system.Exception représente une erreur lors de l’exécution de l’application lorsqu’une exception se produit. La propriété System.Exception.HResult retourne le HRESULT affecté à l’exception spécifique. La propriété System.Exception.Message retourne le message qui décrit l’exception.
C++/CX a été remplacé par C++/WinRT. Toutefois, dans les applications utilisant C++/CX, l’exception Platform ::Exception représente une erreur lors de l’exécution de l’application lorsqu’une exception se produit. La propriété Platform ::Exception ::HResult retourne le HRESULT affecté à l’exception spécifique. La propriété Platform ::Exception ::Message retourne la chaîne fournie par le système associée à la valeur HRESULT .
Pour la plupart des erreurs de validation de paramètre, HRESULT retourné est E_INVALIDARG. Pour certains appels de méthode non valides, le HRESULT retourné est E_ILLEGAL_METHOD_CALL.
Rubriques connexes
Windows developer