HttpClient

API importanti

Usare HttpClient e il resto dell'API dello spazio dei nomi Windows.Web.Http per inviare e ricevere informazioni usando i protocolli HTTP 2.0 e HTTP 1.1.

Panoramica dello spazio dei nomi HttpClient e Windows.Web.Http

Le classi nello spazio dei nomi Windows.Web.Http e le Windows.Web.Http.Headers e gli spazi dei nomi Windows.Web.Http.Filters forniscono un'interfaccia di programmazione per le app UWP (Universal Windows Platform) che fungono da client HTTP per eseguire richieste GET di base o implementare richieste HTTP più avanzate funzionalità elencate di seguito.

  • Metodi per verbi comuni (DELETE, GET, PUTe POST). Ognuna di queste richieste viene inviata come operazione asincrona.

  • Supporto per impostazioni e modelli di autenticazione comuni.

  • Accesso ai dettagli SSL (Secure Sockets Layer) sul trasporto.

  • Possibilità di includere filtri personalizzati nelle app avanzate.

  • Possibilità di ottenere, impostare ed eliminare cookie.

  • Informazioni sullo stato delle richieste HTTP disponibili nei metodi asincroni.

La classe Windows.Web.Http.HttpRequestMessage rappresenta un messaggio di richiesta HTTP inviato da Windows.Web.Http.HttpClient. La classe Windows.Web.Http.HttpResponseMessage rappresenta un messaggio di risposta HTTP ricevuto da una richiesta HTTP. I messaggi HTTP vengono definiti in RFC 2616 da IETF.

Lo spazio dei nomi Windows.Web.Http rappresenta il contenuto HTTP come corpo e intestazioni dell'entità HTTP, inclusi i cookie. Il contenuto HTTP può essere associato a una richiesta HTTP o a una risposta HTTP. Lo spazio dei nomi Windows.Web.Http fornisce una serie di classi diverse per rappresentare il contenuto HTTP.

Il frammento di codice nella sezione "Inviare una semplice richiesta GET su HTTP" usa la classe HttpStringContent per rappresentare la risposta HTTP da una richiesta HTTP GET come stringa.

Lo spazio dei nomi Windows.Web.Http.Headers supporta la creazione di intestazioni e cookie HTTP, che vengono quindi associati come proprietà agli oggetti HttpRequestMessage e HttpResponseMessage.

Inviare una semplice richiesta GET tramite HTTP

Come accennato in precedenza in questo articolo, lo spazio dei nomi windows.Web.Http consente alle app UWP di inviare richieste GET. Il frammento di codice seguente mostra come inviare una richiesta GET a http://www.contoso.com usando le classi Windows.Web.Http.HttpClient e Windows.Web.Http.HttpResponseMessage per leggere la risposta dalla richiesta 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 = "ie";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

header = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.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"ie" };
    if (!headers.UserAgent().TryParseAdd(header))
    {
        throw L"Invalid header value: " + header;
    }

    header = L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.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;
}

Dati POST binari tramite HTTP

L'esempio di codice C++/WinRT seguente illustra l'uso di dati del modulo e una richiesta POST per inviare una piccola quantità di dati binari come caricamento file a un server web. Il codice usa la classe HttpBufferContent per rappresentare i dati binari e la classe HttpMultipartFormDataContent per rappresentare i dati del form multipart.

Nota

La chiamata get (come illustrato nell'esempio di codice riportato di seguito) non è appropriata per un thread dell'interfaccia utente. Per la tecnica corretta da usare in questo caso, vedere Concorrenza e operazioni asincrone con 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;
}

Per registrare il contenuto di un file binario effettivo (anziché i dati binari espliciti usati in precedenza), usare un oggettoHttpStreamContent. Crearne uno e, come argomento al costruttore, passare il valore restituito da una chiamata a StorageFile.OpenReadAsync. Tale metodo restituisce un flusso per i dati all'interno del file binario.

Inoltre, se si sta caricando un file di grandi dimensioni (maggiore di circa 10MB), è consigliabile usare l'API runtime di Windows trasferimento in Background.

Dati POST JSON tramite HTTP

Nell'esempio seguente invia a un endpoint alcuni JSON, quindi scrive il corpo della risposta.

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

Eccezioni in Windows.Web.Http

Viene generata un'eccezione quando viene passata una stringa non valida per un URI (Uniform Resource Identifier) al costruttore per l'oggetto Windows.Foundation.Uri.

.NET: Il tipo di Windows.Foundation.Uri viene visualizzato come System.Uri in C# e VB.

In C# e Visual Basic questo errore può essere evitato usando la classe System.Uri in .NET 4.5 e uno dei metodi System.Uri.TryCreate per testare la stringa ricevuta da un utente prima che venga costruito l'URI.

In C++, non esiste alcun metodo per provare e analizzare una stringa in un URI. Se un'app ottiene l'input dall'utente per il Windows.Foundation.Uri, il costruttore deve trovarsi in un blocco try/catch. In questo modo, se viene generata un'eccezione, l'app può inviare una notifica all'utente e richiedere un nuovo nome host.

La Windows.Web.Http non dispone di una funzione di praticità. Un'app che usa httpClient e altre classi in questo spazio dei nomi deve quindi usare il valore HRESULT.

Nelle app che usano C++/WinRT la struttura winrt::hresult_error rappresenta un'eccezione generata durante l'esecuzione dell'app. La funzione winrt::hresult_error::code restituisce il valore HRESULT assegnato alla specifica eccezione. La funzione winrt::hresult_error::message restituisce la stringa fornita dal sistema associata al valore HRESULT. Per ulteriori informazioni, vedere Gestione degli errori con C++/WinRT

I possibili valori HRESULT sono elencati nel file di intestazione winerror.h. È possibile applicare filtri per specifici valori di HRESULT allo scopo di modificare il comportamento dell'app a seconda della causa dell'eccezione.

Nelle app che usano .NET Framework 4.5 in C#, VB.NET, System.Exception rappresenta un errore che si verifica durante l’esecuzione di un’app in caso di eccezione. La proprietà System.Exception.HResult restituisce il HRESULT assegnato all'eccezione specifica. La proprietà System.Exception.Message restituisce il messaggio che descrive l'eccezione.

C++/CX è stato sostituito da C++/WinRT. Nelle app che usano C++/CX, Platform::Exception rappresenta un errore che si verifica durante l'esecuzione di un'app in caso di eccezione. La proprietà Platform::Exception::HResult restituisce il HRESULT assegnato all'eccezione specifica. La proprietà Platform::Exception::Message restituisce la stringa fornita dal sistema associata al valore HRESULT.

Per gran parte degli errori di convalida dei parametri, il valore HRESULT restituito è E\_INVALIDARG. Per alcune chiamate al metodo non valide, il HRESULT restituito è E_ILLEGAL_METHOD_CALL.