Utilizzare un servizio Web basato su REST

Browse sample. Esplorare l'esempio

REST (Representational State Transfer) è uno stile di architettura per la creazione di servizi Web. Le richieste REST vengono in genere effettuate tramite HTTPS usando gli stessi verbi HTTP usati dai Web browser per recuperare le pagine Web e inviare dati ai server. I verbi sono:

  • GET - Questa operazione viene usata per recuperare dati dal servizio Web.
  • POST - Questa operazione viene usata per creare un nuovo elemento di dati nel servizio Web.
  • PUT - Questa operazione viene usata per aggiornare un elemento di dati nel servizio Web.
  • PATCH - Questa operazione viene usata per aggiornare un elemento di dati nel servizio Web descrivendo un set di istruzioni sulla modalità di modifica dell'elemento.
  • DELETE - Questa operazione viene usata per eliminare un elemento di dati nel servizio Web.

Le API del servizio Web conformi a REST vengono definite tramite:

  • URI di base.
  • Metodi HTTP, ad esempio GET, POST, PUT, PATCH o DELETE.
  • Tipo di supporto per i dati, ad esempio JavaScript Object Notation (JSON).

I servizi Web basati su REST usano in genere messaggi JSON per restituire i dati al client. JSON è un formato di interscambio dati basato su testo che produce payload compatta, che comporta una riduzione dei requisiti di larghezza di banda durante l'invio di dati. La semplicità di REST ha contribuito a renderlo il metodo principale per l'accesso ai servizi Web nelle app per dispositivi mobili.

Nota

L'accesso a un servizio Web richiede spesso la programmazione asincrona. Per altre informazioni sulla programmazione asincrona, vedere Programmazione asincrona con async e await.

Operazioni del servizio Web

Il servizio REST di esempio viene scritto usando ASP.NET Core e fornisce le operazioni seguenti:

Operazione Metodo HTTP URI relativo Parametri
Ottenere un elenco di elementi todo GET /api/todoitems/
Creare un nuovo elemento todo POST /api/todoitems/ Oggetto TodoItem formattato IN FORMATO JSON
Aggiornare un elemento todo PUT /api/todoitems/ Oggetto TodoItem formattato IN FORMATO JSON
Eliminare un elemento todo DELETE /api/todoitems/{id}

L'app MAUI .NET e il servizio Web usano la TodoItem classe per modellare i dati visualizzati e inviati al servizio Web per l'archiviazione:

public class TodoItem
{
    public string ID { get; set; }
    public string Name { get; set; }
    public string Notes { get; set; }
    public bool Done { get; set; }
}

La ID proprietà viene utilizzata per identificare in modo univoco ogni TodoItem oggetto e viene utilizzata dal servizio Web per identificare i dati da aggiornare o eliminare. Ad esempio, per eliminare il TodoItem cui ID è 6bb8a868-dba1-4f1a-93b7-24ebce87e243, l'app MAUI .NET invia una richiesta DELETE a https://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243.

Quando il framework API Web riceve una richiesta, instrada la richiesta a un'azione. Queste azioni sono metodi pubblici nella TodoItemsController classe . Il framework API Web usa il middleware di routing per trovare le corrispondenze con gli URL delle richieste in ingresso ed eseguirne il mapping alle azioni. Le API REST devono usare il routing degli attributi per modellare la funzionalità dell'app come set di risorse le cui operazioni sono rappresentate da verbi HTTP. Il routing con attributi usa un set di attributi per eseguire il mapping delle azioni direttamente ai modelli di route. Per altre informazioni sul routing degli attributi, vedere Routing degli attributi per le API REST. Per altre informazioni sulla creazione del servizio REST con ASP.NET Core, vedere Creazione di servizi back-end per applicazioni per dispositivi mobili native.

Creare l'oggetto HTTPClient

Un'app .NET multipiattaforma dell'interfaccia utente dell'app (.NET MAUI) può usare un servizio Web basato su REST inviando richieste al servizio Web con la HttpClient classe . Questa classe fornisce funzionalità per l'invio di richieste HTTP e la ricezione di risposte HTTP da una risorsa identificata da un URI. Ogni richiesta viene inviata come operazione asincrona.

L'oggetto HttpClient deve essere dichiarato a livello di classe in modo che si trovi per tutto il tempo necessario per l'app per effettuare richieste HTTP:

public class RestService
{
    HttpClient _client;
    JsonSerializerOptions _serializerOptions;

    public List<TodoItem> Items { get; private set; }

    public RestService()
    {
        _client = new HttpClient();
        _serializerOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true
        };
    }
    ...
}

L'oggetto JsonSerializerOptions viene usato per configurare la formattazione del payload JSON ricevuto e inviato al servizio Web. Per altre informazioni, vedere Come creare un'istanza di istanze di JsonSerializerOptions con System.Text.Json.

Recupero dei dati

Il HttpClient.GetAsync metodo viene usato per inviare una richiesta GET al servizio Web specificato dall'URI e quindi ricevere la risposta dal servizio Web:

public async Task<List<TodoItem>> RefreshDataAsync()
{
    Items = new List<TodoItem>();

    Uri uri = new Uri(string.Format(Constants.RestUrl, string.Empty));
    try
    {
        HttpResponseMessage response = await _client.GetAsync(uri);
        if (response.IsSuccessStatusCode)
        {
            string content = await response.Content.ReadAsStringAsync();
            Items = JsonSerializer.Deserialize<List<TodoItem>>(content, _serializerOptions);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"\tERROR {0}", ex.Message);
    }

    return Items;
}

I dati sono ricevuti dal servizio Web come HttpResponseMessage oggetto . Contiene informazioni sulla risposta, inclusi il codice di stato, le intestazioni e qualsiasi corpo. Il servizio REST invia un codice di stato HTTP nella risposta, che può essere ottenuto dalla HttpResponseMessage.IsSuccessStatusCode proprietà , per indicare se la richiesta HTTP ha avuto esito positivo o negativo. Per questa operazione il servizio REST invia il codice di stato HTTP 200 (OK) nella risposta, che indica che la richiesta è riuscita e che le informazioni richieste sono nella risposta.

Se l'operazione HTTP ha esito positivo, il contenuto della risposta viene letto. La HttpResponseMessage.Content proprietà rappresenta il contenuto della risposta e è di tipo HttpContent. La HttpContent classe rappresenta il corpo HTTP e le intestazioni del contenuto, ad esempio Content-Type e Content-Encoding. Il contenuto viene quindi letto in un string oggetto usando il HttpContent.ReadAsStringAsync metodo . viene string quindi deserializzato da JSON a un List di TodoItem oggetti .

Avviso

L'uso del ReadAsStringAsync metodo per recuperare una risposta di grandi dimensioni può avere un impatto negativo sulle prestazioni. In tali circostanze, la risposta deve essere deserializzata direttamente per evitare di dover memorizzarla completamente nel buffer.

Crea flusso

Il HttpClient.PostAsync metodo viene usato per inviare una richiesta POST al servizio Web specificato dall'URI e quindi per ricevere la risposta dal servizio Web:

public async Task SaveTodoItemAsync(TodoItem item, bool isNewItem = false)
{
    Uri uri = new Uri(string.Format(Constants.RestUrl, string.Empty));

    try
    {
        string json = JsonSerializer.Serialize<TodoItem>(item, _serializerOptions);
        StringContent content = new StringContent(json, Encoding.UTF8, "application/json");

        HttpResponseMessage response = null;
        if (isNewItem)
            response = await _client.PostAsync(uri, content);
        else
            response = await _client.PutAsync(uri, content);

        if (response.IsSuccessStatusCode)
            Debug.WriteLine(@"\tTodoItem successfully saved.");
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"\tERROR {0}", ex.Message);
    }
}

In questo esempio l'istanza TodoItem viene serializzata in un payload JSON per l'invio al servizio Web. Questo payload viene quindi incorporato nel corpo del contenuto HTTP che verrà inviato al servizio Web prima che la richiesta venga effettuata con il PostAsync metodo .

Il servizio REST invia un codice di stato HTTP nella risposta, che può essere ottenuto dalla HttpResponseMessage.IsSuccessStatusCode proprietà , per indicare se la richiesta HTTP ha avuto esito positivo o negativo. Le risposte tipiche per questa operazione sono:

  • 201 (CREATED): la richiesta ha generato la creazione di una nuova risorsa prima dell'invio della risposta.
  • 400 (RICHIESTA NON VALIDA): la richiesta non viene riconosciuta dal server.
  • 409 (CONFLICT) - Impossibile eseguire la richiesta a causa di un conflitto nel server.

Aggiornamento dei dati

Il HttpClient.PutAsync metodo viene usato per inviare una richiesta PUT al servizio Web specificato dall'URI e quindi ricevere la risposta dal servizio Web:

public async Task SaveTodoItemAsync(TodoItem item, bool isNewItem = false)
{
  ...
  response = await _client.PutAsync(uri, content);
  ...
}

L'operazione del PutAsync metodo è identica al PostAsync metodo usato per la creazione di dati nel servizio Web. Tuttavia, le possibili risposte inviate dal servizio Web differiscono.

Il servizio REST invia un codice di stato HTTP nella risposta, che può essere ottenuto dalla HttpResponseMessage.IsSuccessStatusCode proprietà , per indicare se la richiesta HTTP ha avuto esito positivo o negativo. Le risposte tipiche per questa operazione sono:

  • 204 (NESSUN CONTENUTO): la richiesta è stata elaborata correttamente e la risposta è intenzionalmente vuota.
  • 400 (RICHIESTA NON VALIDA): la richiesta non viene riconosciuta dal server.
  • 404 (NON TROVATO): la risorsa richiesta non esiste nel server.

Eliminare dati

Il HttpClient.DeleteAsync metodo viene usato per inviare una richiesta DELETE al servizio Web specificato dall'URI e quindi ricevere la risposta dal servizio Web:

public async Task DeleteTodoItemAsync(string id)
{
    Uri uri = new Uri(string.Format(Constants.RestUrl, id));

    try
    {
        HttpResponseMessage response = await _client.DeleteAsync(uri);
        if (response.IsSuccessStatusCode)
            Debug.WriteLine(@"\tTodoItem successfully deleted.");
    }
    catch (Exception ex)
    {
        Debug.WriteLine(@"\tERROR {0}", ex.Message);
    }
}

Il servizio REST invia un codice di stato HTTP nella risposta, che può essere ottenuto dalla HttpResponseMessage.IsSuccessStatusCode proprietà , per indicare se la richiesta HTTP ha avuto esito positivo o negativo. Le risposte tipiche per questa operazione sono:

  • 204 (NESSUN CONTENUTO): la richiesta è stata elaborata correttamente e la risposta è intenzionalmente vuota.
  • 400 (RICHIESTA NON VALIDA): la richiesta non viene riconosciuta dal server.
  • 404 (NON TROVATO): la risorsa richiesta non esiste nel server.

Sviluppo locale

Se si sviluppa un servizio Web REST in locale con un framework come ASP.NET'API Web Core, è possibile eseguire il debug del servizio Web e dell'app MAUI .NET contemporaneamente. In questo scenario, per usare il servizio Web tramite HTTP da emulatori Android e simulatori iOS, è necessario abilitare il traffico HTTP non crittografato nell'app MAUI .NET. Per altre informazioni, vedere Connessione ai servizi Web locali da emulatori Android e simulatori iOS.