Eseguire operazioni HTTP nelle app Web Blazor

Completato

In questa unità si apprenderà come usare IHttpClientFactory per gestire la creazione e lo smaltimento del client HTTP e come usare tale client per eseguire operazioni REST in un'app ASP.NET Blazor. Gli esempi di codice usati in questa unità si basano sull'interazione con un'API che consente di gestire un elenco di frutta archiviato in un database. Le informazioni contenute in questa unità si basano sull'uso di file code-behind in un'app Razor.

Il codice seguente rappresenta il modello di dati a cui si fa riferimento negli esempi di codice:

public class FruitModel
{
    // An id assigned by the database
    public int id { get; set; }
    // The name of the fruit
    public string? name { get; set; }
    // A boolean to indicate if the fruit is in stock
    public bool instock { get; set; }
}

Registrare IHttpClientFactory nell'app

Per aggiungere IHttpClientFactory all'app, registrare AddHttpClient nel file Program.cs. Nell'esempio di codice seguente viene usato il tipo di client denominato, viene impostato l'indirizzo di base dell'API usato nelle operazioni REST e vi si fa riferimento nel resto di questa unità.

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Add IHttpClientFactory to the container and set the name of the factory
// to "FruitAPI". The base address for API requests is also set.
builder.Services.AddHttpClient("FruitAPI", httpClient =>
{
    httpClient.BaseAddress = new Uri("http://localhost:5050/");
});

var app = builder.Build();

Identificare i requisiti dell'operazione nell'API

Prima di eseguire operazioni con un'API, è necessario identificare le aspettative dell'API:

  • Endpoint dell'API: identificare l'endpoint per l'operazione in modo da poter modificare correttamente l'URI archiviato nell'indirizzo di base, se necessario.
  • Requisiti dei dati: identificare se l'operazione restituisce/prevede una matrice di dati o solo un singolo dato.

Nota

Gli esempi di codice in tutto il resto di questa unità presuppongono che ogni operazione HTTP venga gestita in una pagina separata nella soluzione.

Eseguire un'operazione GET

Un'operazione GET non deve inviare un corpo e viene usata (come indica il nome del metodo) per recuperare i dati da una risorsa. Per eseguire un'operazione HTTP GET, in base a HttpClient e a un URI, usare il metodo HttpClient.GetAsync. Ad esempio, se si vuole creare una tabella nella home page dell'app Razor Page (Home.razor) in modo da visualizzare i risultati di un'operazione GET, è necessario aggiungere quanto segue al code-behind (Home.razor.cs):

  • Usare l'inserimento delle dipendenze per aggiungere IHttpClientFactory al modello di pagina.
  • Creare un'istanza di HttpClient
  • Eseguire l'operazione GETe deserializza i risultati nel modello di dati.

L'esempio di codice seguente illustra come eseguire un'operazione GET. Assicurarsi di leggere i commenti nel codice.

public partial class Home : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    /* Add the data model, an array is expected as a response */
    private IEnumerable<FruitModel>? _fruitList;

    // Begin GET operation when the component is initialized
    protected override async Task OnInitializedAsync()
    {
        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Perform the GET request and store the response. The parameter
        // in GetAsync specifies the endpoint in the API 
        using HttpResponseMessage response = await httpClient.GetAsync("/fruits");

        // If the request is successful deserialize the results into the data model
        if (response.IsSuccessStatusCode)
        {
            using var contentStream = await response.Content.ReadAsStreamAsync();
            _fruitList = await JsonSerializer.DeserializeAsync<IEnumerable<FruitModel>>(contentStream);
        }
        else
        {
            // If the request is unsuccessful, log the error message
            Console.WriteLine($"Failed to load fruit list. Status code: {response.StatusCode}");
        }
    }
}

Eseguire un'operazione POST

Un'operazione POST deve inviare un corpo e viene usata per aggiungere dati a una risorsa. Per eseguire un'operazione HTTP POST, in base a HttpClient e a un URI, usare il metodo HttpClient.PostAsync. Se si vuole usare un modulo per aggiungere elementi ai dati nella home page, è necessario:

  • Usare l'inserimento delle dipendenze per aggiungere IHttpClientFactory al modello di pagina.
  • Associare i dati al modulo usando il modello EditForm o EditContext.
  • Serializzare i dati da aggiungere usando il metodo JsonSerializer.Serialize.
  • Creare un'istanza di HttpClient
  • Eseguire l'operazione POST.

Nota

Seguendo il modello di progetto di una pagina separata per ogni operazione REST, l'operazione POST viene eseguita in una pagina Add.razor con l'esempio di codice nel file code-behind Add.razor.cs.

L'esempio di codice seguente illustra come eseguire un'operazione POST. Assicurarsi di leggere i commenti nel codice.

namespace FruitWebApp.Components.Pages;

public partial class Add : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    // NavigationManager set using dependency injection
    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    // Add the data model and bind the form data to it
    [SupplyParameterFromForm]
    private FruitModel? _fruitList { get; set; }

    protected override void OnInitialized() => _fruitList ??= new();

    // Begin POST operation code
    private async Task Submit()
    {
        // Serialize the information to be added to the database
        var jsonContent = new StringContent(JsonSerializer.Serialize(_fruitList),
            Encoding.UTF8,
            "application/json");

        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Execute the POST request and store the response. The response will contain the new record's ID
        using HttpResponseMessage response = await httpClient.PostAsync("/fruits", jsonContent);

        // Check if the operation was successful, and navigate to the home page if it was
        if (response.IsSuccessStatusCode)
        {
            NavigationManager?.NavigateTo("/");
        }
        else
        {
            Console.WriteLine("Failed to add fruit. Status code: {response.StatusCode}");
        }
    }
}

Eseguire altre operazioni REST

Altre operazioni come PUT e DELETE seguono lo stesso modello illustrato in precedenza. La tabella seguente definisce le operazioni REST comuni insieme al metodo HttpClient associato:

Richiedi metodo Definizione
GET HttpClient.GetAsync Recupera una risorsa
POST HttpClient.PostAsync Crea una nuova risorsa
PUT HttpClient.PutAsync Aggiorna una risorsa esistente o ne crea una nuova se non ne esistono
DELETE HttpClient.DeleteAsync Elimina una risorsa
PATCH HttpClient.PatchAsync Aggiorna parzialmente una risorsa esistente