Utilizzare un servizio REST con HttpClient

Completato

Molti servizi Web moderni implementano l'architettura REST. Questa struttura consente a un servizio Web di esporre operazioni e dati attraverso una serie di endpoint ben definiti. Le richieste inviate dalle app client a un servizio Web REST per recuperare, modificare, creare o eliminare dati usano un set predefinito di verbi. Un servizio Web REST risponde a queste richieste in modo standard. Questo approccio semplifica la creazione di app client.

Il modello REST è basato sul protocollo HTTP. Un'applicazione .NET MAUI può inviare richieste a un servizio Web REST usando la classe HttpClient. In questa unità si apprenderà HttpClient come usarlo per interagire con un servizio Web REST.

Che cos'è la classe HttpClient?

HttpClient è una classe .NET che un'app può usare per inviare richieste HTTP e ricevere risposte HTTP da un servizio Web REST. Un set di URI identifica le risorse esposte dal servizio Web. Un URI combina l'indirizzo del servizio Web con il nome di una risorsa disponibile a tale indirizzo.

La HttpClient classe usa un'API basata su attività per le prestazioni e consente di accedere alle informazioni nei messaggi di richiesta, ad esempio intestazioni HTTP e codici di stato, nonché corpi di messaggi che contengono i dati effettivi inviati e ricevuti.

Diagram showing how a client app uses an HttpClient object to send and receive HTTP messages and responses

La classe HttpClient è disponibile nello spazio dei nomi System.Net.Http. Un'app può creare un oggetto HttpClient utilizzando il costruttore predefinito:

using System.Net.Http;
...

var client = new HttpClient();

Eseguire operazioni CRUD con un oggetto HttpClient

Un servizio Web REST consente a un client di eseguire operazioni su dati tramite un set di verbi HTTP. Il processo del verbo HTTP consiste nell'indicare l'azione desiderata da eseguire su una risorsa. I verbi HTTP sono molti, ma i quattro più comuni sono POST, GET, PUT e DELETE. Un servizio può implementare questi verbi per consentire a un'applicazione client di gestire il ciclo di vita degli oggetti eseguendo operazioni di creazione, lettura, aggiornamento ed eliminazione (CRUD) nel modo seguente:

  • Il verbo POST indica che si vuole creare una nuova risorsa.

  • Il verbo GET indica che si vuole recuperare una risorsa.

  • Il verbo PUT indica che si vuole aggiornare una risorsa.

  • Il verbo DELETE indica che si vuole eliminare una risorsa.

Diagram showing the basic CRUD operations that a REST service can implement, including get, post, put and delete.

Creare una nuova risorsa con HttpClient

Per creare una nuova risorsa usando HttpClient, è possibile usare il metodo SendAsync per passarla a un oggetto HttpRequestMessage.

HttpRequestMessage deve modellare la richiesta inviata al servizio Web. Specificare il verbo HTTP, l'URL del servizio Web e popolare qualsiasi payload da inviare tramite la proprietà HttpRequestMessage.Content.

HttpClient client = new HttpClient();

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url);
message.Content = JsonContent.Create<Part>(part);

HttpResponseMessage response = await client.SendAsync(message);

Questo frammento di codice esegue le attività seguenti:

  • Crea un'istanza di HttpClient chiamata client usata per inviare un messaggio.
  • Crea un'istanza di HttpRequestMessage chiamata messaggio usata per modellare il messaggio. Il messaggio contiene il verbo HTTP e l'URL.
  • Imposta la proprietà Content di HttpRequestMessage, usando la funzione JsonContent.Create. Questa funzione serializza automaticamente la variabile della parte in JSON adatta per l'invio al servizio Web.
  • Il messaggio viene inviato usando l'oggetto HttpClient. Quando HttpResponseMessage viene restituito contiene informazioni come il codice di stato e le informazioni restituite dal servizio Web.

Leggere una risorsa con HttpClient

È possibile leggere una risorsa da un servizio Web usando la stessa tecnica descritta in precedenza, ad eccezione dell'inizializzazione di HttpRequestMessage con un oggetto HttpMethod.Get. Tuttavia, ha HttpClient un paio di metodi pratici che forniscono collegamenti.

Per leggere una risorsa con HTTPClient, usare il metodo GetStringAsync come illustrato nell'esempio seguente:

HttpClient client = new HttpClient();

string text = await client.GetStringAsync("https://...");

Il GetStringAsync metodo accetta un URI che fa riferimento alla risorsa e restituisce una risposta come stringa. La stringa di risposta è la risorsa richiesta dall'app. Il formato response-data è l'impostazione predefinita per il servizio richiesto, ad esempio JSON o XML. Un'app può indicare al servizio Web che i dati devono essere restituiti in un formato specifico aggiungendo l'intestazione MediaTypeWithQualityHeaderValue. Ad esempio, se l'app richiede che i dati vengano inviati in formato JSON, può essere usato il codice seguente:

HttpClient client = new HttpClient();

client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

In questo esempio il risultato viene restituito come stringa e contiene solo il corpo del messaggio di risposta. Per ottenere l'intera risposta, incluse intestazioni, corpo e codice di stato, chiamare il metodo GetAsync. I dati vengono restituiti come un oggetto HttpResponseMessage.

Aggiornare una risorsa con HttpClient

Per aggiornare una risorsa con HttpClient, usare HttpRequestMessage inizializzato con un verbo PUT. Il codice seguente è simile a quello necessario per creare una nuova risorsa:

HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Put, url);

message.Content = JsonContent.Create<Part>(part);

HttpResponseMessage response = await client.SendAsync(message);

Nota

La differenza fondamentale tra POST e PUT è l’idempotenza. Se la richiesta PUT viene ripetuta più volte, la risorsa verrà aggiornata con i soliti dati e l'effetto sarà lo stesso come se la richiesta fosse stata inviata una sola volta. Se si esegue la stessa POST richiesta più volte, il risultato sarà il servizio REST che crea più copie della risorsa.

Eliminare una risorsa con HttpClient

Per eliminare una risorsa usando HttpClient, chiamare SendAsync con HttpRequestMessage inizializzato con un verbo DELETE:

HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Delete, url);

HttpResponseMessage response = await client.SendAsync(message);

La risposta contiene le intestazioni, il codice di stato e l'oggetto eliminato.

Gestire le risposte da una richiesta

Tutte le richieste HTTP restituiscono un messaggio di risposta. I dati nella risposta dipendono dal verbo inviato dall'app. Ad esempio, il corpo della risposta di una richiesta GET HTTP contiene i dati per la risorsa richiesta.

Il corpo della risposta di una richiesta POST restituisce una copia della risorsa creata, ma il corpo della risposta di una richiesta PUT deve essere vuoto.

È consigliabile controllare e gestire sempre il codice di stato nel messaggio di risposta. Se questo codice di stato è compreso nell'intervallo 200 (200, 201, 202 e così via), l'operazione viene considerata riuscita, anche se potrebbero essere necessarie ulteriori informazioni in un secondo momento.

Un codice di stato nell'intervallo 300 indica che la richiesta potrebbe essere stata reindirizzata dal servizio Web a un indirizzo diverso, probabilmente come risultato dello spostamento di una risorsa in un percorso diverso.

Un codice di stato nell'intervallo 400 indica un errore del client o dell'applicazione. Ad esempio, il codice di stato 403 indica che il servizio Web richiede l'autenticazione dell'utente, che però non è stata effettuata dall’app. Il codice di stato 404 si verifica quando l'app tenta di accedere a una risorsa che non esiste.

I codici di stato nell'intervallo 500 indicano un errore sul lato server. Ad esempio, il servizio non è disponibile o è troppo occupato per gestire la richiesta.

L'oggetto HttpResponseMessage restituito da una richiesta inviata tramite un oggetto HttpClient può astrarre gran parte della complessità della gestione dei diversi codici di stato. Questo frammento di codice mostra come verificare che il codice di stato in un messaggio di risposta indichi l'esito positivo e come gestire i codici di stato che indicano un certo tipo di errori.

static readonly HttpClient client = new HttpClient();

...
// Call asynchronous network methods in a try/catch block to handle exceptions.
try
{
    //... Initiate the HttpRequest

    HttpResponseMessage response = await client.SendAsync(msg);
    response.EnsureSuccessStatusCode(); // Check that the status code is in the 200 range. Throw an HttpRequestException if not
    
    string responseBody = await response.Content.ReadAsStringAsync();
    
    ... // Handle the response
}
catch(HttpRequestException e)
{
    ... // Handle any status codes that indicate an error. 
        // The status code is available in the field e.StatusCode
}

Verifica delle conoscenze

1.

Quale verbo HTTP viene usato per creare una nuova risorsa in un servizio Web REST?

2.

Quale metodo della classe HttpResponseMessage deve essere chiamato per verificare che una richiesta HTTP sia riuscita?