Chiamare un'API Web da ASP.NET Core Blazor

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere Criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Questo articolo descrive come chiamare un'API Web da un'app Blazor .

Pacchetto

Il System.Net.Http.Json pacchetto fornisce metodi di estensione per System.Net.Http.HttpClient e System.Net.Http.HttpContent che eseguono la serializzazione automatica e la deserializzazione tramite System.Text.Json. Il System.Net.Http.Json pacchetto viene fornito dal framework condiviso .NET e non richiede l'aggiunta di un riferimento al pacchetto all'app.

App di esempio

Vedere le app di esempio nel dotnet/blazor-samples repository GitHub.

BlazorWebAppCallWebApi

Chiamare un'API Web todo (non nell'elenco Blazor Web Appdi todo ) da un oggetto Blazor Web App:

  • Backend: un'app per le API Web per la gestione di un elenco di attività, in base alle API minime. L'app per le API Web è un'app separata da Blazor Web App, possibilmente ospitata in un server diverso.
  • BlazorApp/BlazorApp.ClientBlazor Web App: oggetto che chiama l'app per le API Web con un HttpClient oggetto per le operazioni di elenco todo, ad esempio la creazione, la lettura, l'aggiornamento e l'eliminazione di elementi (CRUD) dall'elenco todo.

Per il rendering lato client (CSR), che include componenti Interactive WebAssembly e componenti auto che hanno adottato csr, le chiamate vengono effettuate con un file preconfigurato HttpClient registrato nel Program file del progetto client (BlazorApp.Client):

builder.Services.AddScoped(sp =>
    new HttpClient
    {
        BaseAddress = new Uri(builder.Configuration["FrontendUrl"] ?? "https://localhost:5002")
    });

Per il rendering lato server (SSR), che include componenti server prerenderati e interattivi, componenti WebAssembly prerenderati e componenti automatici prerenderati o adottati in SSR, le chiamate vengono effettuate con un HttpClient registrato nel Program file del progetto server (BlazorApp):

builder.Services.AddHttpClient();

Chiamare un'API di elenco di film interna (all'interno di Blazor Web App) in cui risiede l'API nel progetto server di Blazor Web App:

  • BlazorApp: oggetto Blazor Web App che gestisce un elenco di film:
    • Quando le operazioni vengono eseguite nell'elenco di film all'interno dell'app nel server, vengono usate le normali chiamate API.
    • Quando le chiamate API vengono effettuate da un client basato sul Web, viene usata un'API Web per le operazioni di elenco di film, in base alle API minime.
  • BlazorApp.Client: progetto client di Blazor Web App, che contiene componenti Interactive WebAssembly e Auto per la gestione degli utenti dell'elenco di film.

Per CSR, che include componenti Interactive WebAssembly e Componenti automatici che hanno adottato csr, le chiamate all'API vengono effettuate tramite un servizio basato su client (ClientMovieService) che usa un file preconfigurato HttpClient registrato nel Program file del progetto client (BlazorApp.Client). Poiché queste chiamate vengono effettuate tramite un Web pubblico o privato, l'API elenco di film è un'API Web.

L'esempio seguente ottiene un elenco di film dall'endpoint /movies :

public class ClientMovieService(HttpClient http) : IMovieService
{
    public async Task<Movie[]> GetMoviesAsync(bool watchedMovies) => 
        await http.GetFromJsonAsync<Movie[]>("movies") ?? [];
}

Per SSR, che include componenti server prerenderati e interattivi, componenti WebAssembly prerenderati e componenti automatici prerenderati o adottati in SSR, le chiamate vengono effettuate direttamente tramite un servizio basato su server (ServerMovieService). L'API non si basa su una rete, quindi è un'API standard per le operazioni CRUD dell'elenco di film.

L'esempio seguente ottiene un elenco di film:

public class ServerMovieService(MovieContext db) : IMovieService
{
    public async Task<Movie[]> GetMoviesAsync(bool watchedMovies) => 
        watchedMovies ? 
        await db.Movies.Where(t => t.IsWatched).ToArrayAsync() : 
        await db.Movies.ToArrayAsync();
}

BlazorWebAppCallWebApi_Weather

Un'app di esempio di dati meteo che usa il rendering in streaming per i dati meteo.

BlazorWebAssemblyCallWebApi

Chiama un'API Web todo list da un'app Blazor WebAssembly :

  • Backend: un'app per le API Web per la gestione di un elenco di attività, in base alle API minime.
  • BlazorTodoBlazor WebAssembly: un'app che chiama l'API Web con un preconfigurato HttpClient per le operazioni CRUD di elenco todo.

Scenari lato server per la chiamata di API Web esterne

I componenti basati su server chiamano API Web esterne usando HttpClient istanze, in genere create con IHttpClientFactory. Per indicazioni applicabili alle app sul lato server, vedere Effettuare richieste HTTP con IHttpClientFactory in ASP.NET Core.

Un'app lato server non include un HttpClient servizio. Fornire un oggetto HttpClient all'app usando l'infrastruttura HttpClientfactory.

Nel file Program:

builder.Services.AddHttpClient();

Il componente seguente Razor invia una richiesta a un'API Web per i rami GitHub in modo simile all'esempio utilizzo di base nell'articolo Effettuare richieste HTTP usando IHttpClientFactory in ASP.NET Core.

CallWebAPI.razor:

@page "/call-web-api"
@using System.Text.Json
@using System.Text.Json.Serialization
@inject IHttpClientFactory ClientFactory

<h1>Call web API from a Blazor Server Razor component</h1>

@if (getBranchesError || branches is null)
{
    <p>Unable to get branches from GitHub. Please try again later.</p>
}
else
{
    <ul>
        @foreach (var branch in branches)
        {
            <li>@branch.Name</li>
        }
    </ul>
}

@code {
    private IEnumerable<GitHubBranch>? branches = [];
    private bool getBranchesError;
    private bool shouldRender;

    protected override bool ShouldRender() => shouldRender;

    protected override async Task OnInitializedAsync()
    {
        var request = new HttpRequestMessage(HttpMethod.Get,
            "https://api.github.com/repos/dotnet/AspNetCore.Docs/branches");
        request.Headers.Add("Accept", "application/vnd.github.v3+json");
        request.Headers.Add("User-Agent", "HttpClientFactory-Sample");

        var client = ClientFactory.CreateClient();

        var response = await client.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            using var responseStream = await response.Content.ReadAsStreamAsync();
            branches = await JsonSerializer.DeserializeAsync
                <IEnumerable<GitHubBranch>>(responseStream);
        }
        else
        {
            getBranchesError = true;
        }

        shouldRender = true;
    }

    public class GitHubBranch
    {
        [JsonPropertyName("name")]
        public string? Name { get; set; }
    }
}

Nell'esempio precedente per C# 12 o versione successiva viene creata una matrice vuota ([]) per la branches variabile. Per le versioni precedenti di C#, creare una matrice vuota (Array.Empty<GitHubBranch>()).

Per un esempio di lavoro aggiuntivo, vedere l'esempio di caricamento di file sul lato server che carica i file in un controller API Web nell'articolo caricamenti di file core Blazor ASP.NET.

Astrazioni del servizio per le chiamate API Web

Questa sezione si applica a Blazor Web Apps che gestisce un'API Web nel progetto server o trasforma le chiamate API Web a un'API Web esterna.

Quando si usano le modalità interattive WebAssembly e Rendering automatico, i componenti vengono pre-gestiti per impostazione predefinita.When using the interactive WebAssembly and Auto render mode, components are prerendered by default. Il rendering dei componenti automatici viene eseguito inizialmente anche in modo interattivo dal server prima che il Blazor bundle venga scaricato nel client e il runtime sul lato client venga attivato. Ciò significa che i componenti che usano queste modalità di rendering devono essere progettati in modo che vengano eseguiti correttamente sia dal client che dal server. Se il componente deve chiamare un'API basata su progetto server o trasformare una richiesta a un'API Web esterna (una esterna a Blazor Web App) quando è in esecuzione nel client, l'approccio consigliato consiste nell'astrarre tale chiamata API dietro un'interfaccia del servizio e implementare versioni client e server del servizio:

  • La versione client chiama l'API Web con un oggetto preconfigurato HttpClient.
  • La versione del server può in genere accedere direttamente alle risorse lato server. L'inserimento di un oggetto HttpClient nel server che effettua chiamate al server non è consigliato, perché in genere la richiesta di rete non è necessaria. In alternativa, l'API potrebbe essere esterna al progetto server, ma è necessaria un'astrazione del servizio per il server per trasformare la richiesta in qualche modo, ad esempio per aggiungere un token di accesso a una richiesta proxy.

Quando si usa la modalità di rendering WebAssembly, è anche possibile disabilitare la prerendering, in modo che i componenti eseguano solo il rendering dal client. Per altre informazioni, vedere ASP.NET Modalità di rendering coreBlazor.

Esempi (app di esempio):

  • API Web elenco film nell'app BlazorWebAppCallWebApi di esempio.
  • API Web per il rendering dei dati meteo in streaming nell'app BlazorWebAppCallWebApi_Weather di esempio.
  • Dati meteo restituiti al client nelle BlazorWebAppOidc app di esempio (modello BFF) o BlazorWebAppOidcBff (modello BFF). Queste app illustrano chiamate API sicure (Web). Per altre informazioni, vedere Proteggere un ASP.NET Core Blazor Web App con OpenID Connect (OIDC).

Blazor Web App API Web esterne

Questa sezione si applica a Blazor Web Apps che chiamano un'API Web gestita da un progetto separato (esterno), possibilmente ospitato in un server diverso.

Blazor Web Appin genere esegue il prerendere i componenti WebAssembly sul lato client e i componenti automatici vengono visualizzati nel server durante il rendering statico o interattivo sul lato server (SSR). HttpClient i servizi non vengono registrati per impostazione predefinita nel progetto principale di un Blazor Web Appoggetto . Se l'app viene eseguita con solo i HttpClient servizi registrati nel .Client progetto, come descritto nella sezione Aggiungere il HttpClient servizio , l'esecuzione dell'app genera un errore di runtime:

InvalidOperationException: impossibile fornire un valore per la proprietà 'Http' nel tipo '... {COMPONENT}'. Non esiste alcun servizio registrato di tipo 'System.Net.Http.HttpClient'.

Usare uno degli approcci seguenti:

  • Aggiungere i HttpClient servizi al progetto server per rendere disponibile durante SSR HttpClient . Usare la registrazione del servizio seguente nel file del progetto server Program :

    builder.Services.AddHttpClient();
    

    HttpClient i servizi vengono forniti dal framework condiviso, quindi non è necessario un riferimento al pacchetto nel file di progetto dell'app.

    Esempio: API Web elenco todo nell'app BlazorWebAppCallWebApi di esempio

  • Se il prerendering non è necessario per un componente WebAssembly che chiama l'API Web, disabilitare la prerendering seguendo le indicazioni riportate in ASP.NET modalità di rendering coreBlazor. Se si adotta questo approccio, non è necessario aggiungere HttpClient servizi al progetto principale di Blazor Web App perché il componente non è prerenderato nel server.

Per altre informazioni, vedere I servizi sul lato client non riescono a risolvere durante la pre-esecuzione del servizio.

Dati prerisorsi

Quando si esegue la pre-distribuzione, i componenti eseguono il rendering due volte: prima in modo statico, quindi in modo interattivo. Lo stato non passa automaticamente dal componente prerenderato a quello interattivo. Se un componente esegue operazioni di inizializzazione asincrone ed esegue il rendering di contenuto diverso per stati diversi durante l'inizializzazione, ad esempio un "Caricamento..." indicatore di stato, è possibile che venga visualizzato uno sfarfallio quando il componente esegue il rendering due volte.

Per risolvere questo problema, è possibile scorrere lo stato prerenderato usando l'API Stato componente persistente, illustrata dalle BlazorWebAppCallWebApi app di esempio e BlazorWebAppCallWebApi_Weather . Quando il componente esegue il rendering interattivo, può eseguire lo stesso rendering usando lo stesso stato. Tuttavia, l'API non funziona attualmente con lo spostamento avanzato, che è possibile aggirare disabilitando la navigazione avanzata nei collegamenti alla pagina (data-enhanced-nav=false). Per ulteriori informazioni, vedi le seguenti risorse:

Aggiungere il HttpClient servizio

Le indicazioni contenute in questa sezione si applicano agli scenari lato client.

I componenti lato client chiamano API Web usando un servizio preconfigurato, incentrato HttpClient sull'esecuzione di richieste al server di origine. È possibile creare configurazioni di servizio aggiuntive HttpClient per altre API Web nel codice per sviluppatori. Le richieste sono composte usando Blazor helper JSON o con HttpRequestMessage. Le richieste possono includere la configurazione dell'opzione fetch API .

Gli esempi di configurazione in questa sezione sono utili solo quando viene chiamata una singola API Web per una singola HttpClient istanza nell'app. Quando l'app deve chiamare più API Web, ognuna con il proprio indirizzo di base e configurazione, è possibile adottare gli approcci seguenti, illustrati più avanti in questo articolo:

Program Nel file aggiungere un HttpClient servizio se non è già presente da un Blazor modello di progetto usato per creare l'app:

builder.Services.AddScoped(sp => 
    new HttpClient
    {
        BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
    });

L'esempio precedente imposta l'indirizzo di base con builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), che ottiene l'indirizzo di base per l'app ed è in genere derivato dal <base> valore del href tag nella pagina host.

I casi d'uso più comuni per l'uso dell'indirizzo di base del client sono:

  • Il progetto client (.Client) di ( Blazor Web App .NET 8 o versione successiva) effettua chiamate API Web dai componenti o dal codice WebAssembly eseguito nel client in WebAssembly alle API nell'app server.
  • Il progetto client (Client) di un'app ospitata Blazor WebAssembly effettua chiamate API Web al progetto server (Server). Si noti che il modello di progetto ospitato Blazor WebAssembly non è più disponibile in .NET 8 o versione successiva. Tuttavia, le app ospitate Blazor WebAssembly rimangono supportate per .NET 8.

Se si chiama un'API Web esterna (non nello stesso spazio URL dell'app client), impostare l'URI sull'indirizzo di base dell'API Web. L'esempio seguente imposta l'indirizzo di base dell'API Web su https://localhost:5001, in cui un'app per le API Web separata è in esecuzione e pronta per rispondere alle richieste dall'app client:

builder.Services.AddScoped(sp => 
    new HttpClient
    {
        BaseAddress = new Uri("https://localhost:5001")
    });

Helper JSON

HttpClient è disponibile come servizio preconfigurato per l'esecuzione di richieste al server di origine.

HttpClient e gli helper JSON (System.Net.Http.Json.HttpClientJsonExtensions) vengono usati anche per chiamare endpoint API Web di terze parti. HttpClientviene implementato usando l'API Fetch del browser ed è soggetto alle relative limitazioni, inclusa l'applicazione dei criteri di stessa origine, che viene descritta più avanti in questo articolo nella sezione Condivisione risorse tra le origini (CORS).

L'indirizzo di base del client è impostato sull'indirizzo del server di origine. Inserire un'istanza HttpClient in un componente usando la @inject direttiva :

@using System.Net.Http
@inject HttpClient Http

Usare lo spazio dei nomi per l'accesso System.Net.Http.Json a HttpClientJsonExtensions, tra cui GetFromJsonAsync, PutAsJsonAsynce PostAsJsonAsync:

@using System.Net.Http.Json

Le sezioni seguenti illustrano gli helper JSON:

System.Net.Http include metodi aggiuntivi per l'invio di richieste HTTP e la ricezione di risposte HTTP, ad esempio per inviare una richiesta DELETE. Per altre informazioni, vedere la sezione DELETE e metodi di estensione aggiuntivi.

GET da JSON (GetFromJsonAsync)

GetFromJsonAsync invia una richiesta HTTP GET e analizza il corpo della risposta JSON per creare un oggetto.

Nel codice del componente seguente l'oggetto todoItems viene visualizzato dal componente . GetFromJsonAsync viene chiamato al termine dell'inizializzazione del componente (OnInitializedAsync).

todoItems = await Http.GetFromJsonAsync<TodoItem[]>("todoitems");

POST come JSON (PostAsJsonAsync)

PostAsJsonAsync invia una richiesta POST all'URI specificato contenente il valore serializzato come JSON nel corpo della richiesta.

Nel codice del componente seguente viene newItemName fornito da un elemento associato del componente. Il AddItem metodo viene attivato selezionando un <button> elemento .

await Http.PostAsJsonAsync("todoitems", addItem);

PostAsJsonAsync restituisce un oggetto HttpResponseMessage. Per deserializzare il contenuto JSON dal messaggio di risposta, usare il metodo di ReadFromJsonAsync estensione. L'esempio seguente legge i dati meteo JSON come matrice:

var content = await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ?? 
    Array.Empty<WeatherForecast>();

PUT come JSON (PutAsJsonAsync)

PutAsJsonAsync invia una richiesta HTTP PUT con contenuto con codifica JSON.

Nel codice del componente seguente i editItem valori per Name e IsCompleted vengono forniti da elementi associati del componente. L'elemento viene impostato quando l'elemento Id viene selezionato in un'altra parte dell'interfaccia utente (non visualizzata) e EditItem viene chiamato . Il SaveItem metodo viene attivato selezionando l'elemento <button> . L'esempio seguente non mostra il caricamento todoItems per brevità. Per un esempio di caricamento degli elementi, vedere la sezione GET from JSON (GetFromJsonAsync).

await Http.PutAsJsonAsync($"todoitems/{editItem.Id}", editItem);

PutAsJsonAsync restituisce un oggetto HttpResponseMessage. Per deserializzare il contenuto JSON dal messaggio di risposta, usare il metodo di ReadFromJsonAsync estensione. L'esempio seguente legge i dati meteo JSON come matrice:

var content = await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ?? 
    Array.Empty<WeatherForecast>();

PATCH come JSON (PatchAsJsonAsync)

PatchAsJsonAsync invia una richiesta HTTP PATCH con contenuto con codifica JSON.

Nota

Per altre informazioni, vedere JsonPatch in ASP.NET API Web Core.

Nell'esempio PatchAsJsonAsync seguente riceve un documento JSON PATCH come stringa di testo normale con virgolette di escape:

await Http.PatchAsJsonAsync(
    $"todoitems/{id}", 
    "[{\"operationType\":2,\"path\":\"/IsComplete\",\"op\":\"replace\",\"value\":true}]");

PatchAsJsonAsync restituisce un oggetto HttpResponseMessage. Per deserializzare il contenuto JSON dal messaggio di risposta, usare il metodo di ReadFromJsonAsync estensione. L'esempio seguente legge i dati dell'elemento todo JSON come matrice. Se non vengono restituiti dati di elemento dal metodo, viene creata una matrice vuota, quindi content non è null dopo l'esecuzione dell'istruzione:

var response = await Http.PatchAsJsonAsync(...);
var content = await response.Content.ReadFromJsonAsync<TodoItem[]>() ??
    Array.Empty<TodoItem>();

Disposto con rientro, spaziatura e virgolette senza caratteri di escape, il documento PATCH non codificato viene visualizzato come json seguente:

[
  {
    "operationType": 2,
    "path": "/IsComplete",
    "op": "replace",
    "value": true
  }
]

Per semplificare la creazione di documenti PATCH nell'app che emette richieste PATCH, un'app può usare il supporto PATCH JSON .NET, come illustrato nelle indicazioni seguenti.

Installare il Microsoft.AspNetCore.JsonPatch pacchetto NuGet e usare le funzionalità API del pacchetto per comporre un oggetto JsonPatchDocument per una richiesta PATCH.

Nota

Per indicazioni sull'aggiunta di pacchetti alle app .NET, vedere gli articoli sotto Installare e gestire pacchetti in Flusso di lavoro dell'utilizzo di pacchetti (documentazione di NuGet). Confermare le versioni corrette del pacchetto all'indirizzo NuGet.org.

Aggiungere @using direttive per gli spazi dei System.Text.Jsonnomi , System.Text.Json.Serializatione Microsoft.AspNetCore.JsonPatch all'inizio del Razor componente:

@using System.Text.Json
@using System.Text.Json.Serialization
@using Microsoft.AspNetCore.JsonPatch

JsonPatchDocument Comporre per un TodoItem oggetto con IsComplete impostato su true usando il Replace metodo :

var patchDocument = new JsonPatchDocument<TodoItem>()
    .Replace(p => p.IsComplete, true);

Passare le operazioni del documento (patchDocument.Operations) alla PatchAsJsonAsync chiamata:

private async Task UpdateItem(long id)
{
    await Http.PatchAsJsonAsync(
        $"todoitems/{id}", 
        patchDocument.Operations, 
        new JsonSerializerOptions()
        {
            DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault
        });
}

JsonSerializerOptions.DefaultIgnoreCondition è impostato su JsonIgnoreCondition.WhenWritingDefault per ignorare una proprietà solo se è uguale al valore predefinito per il relativo tipo.

Aggiungere JsonSerializerOptions.WriteIndented impostato su true se si vuole presentare il payload JSON in un formato piacevole per la visualizzazione. La scrittura di JSON con rientro non ha alcun impatto sull'elaborazione delle richieste PATCH e in genere non viene eseguita nelle app di produzione per le richieste api Web.

Seguire le indicazioni riportate nell'articolo JsonPatch in ASP.NET API Web Core per aggiungere un'azione del controller PATCH all'API Web. In alternativa, l'elaborazione delle richieste PATCH può essere implementata come API minima con la procedura seguente.

Aggiungere un riferimento al pacchetto NuGet all'app Microsoft.AspNetCore.Mvc.NewtonsoftJson per le API Web.

Nota

Non è necessario aggiungere un riferimento al pacchetto per il Microsoft.AspNetCore.JsonPatch pacchetto all'app perché il riferimento al pacchetto aggiunge automaticamente un riferimento al Microsoft.AspNetCore.Mvc.NewtonsoftJson pacchetto per Microsoft.AspNetCore.JsonPatch.

Program Nel file aggiungere una @using direttiva per lo spazio dei Microsoft.AspNetCore.JsonPatch nomi :

using Microsoft.AspNetCore.JsonPatch;

Fornire l'endpoint alla pipeline di elaborazione delle richieste dell'API Web:

app.MapPatch("/todoitems/{id}", async (long id, TodoContext db) =>
{
    if (await db.TodoItems.FindAsync(id) is TodoItem todo)
    {
        var patchDocument = 
            new JsonPatchDocument<TodoItem>().Replace(p => p.IsComplete, true);
        patchDocument.ApplyTo(todo);
        await db.SaveChangesAsync();

        return TypedResults.Ok(todo);
    }

    return TypedResults.NoContent();
});

Avviso

Come per gli altri esempi nell'articolo JsonPatch in ASP.NET API Web Core, l'API PATCH precedente non protegge l'API Web da attacchi di over-post. Per altre informazioni, vedere Esercitazione: Creare un'API Web con ASP.NET Core.

Per un'esperienza PATCH completamente funzionante, vedi l'app BlazorWebAppCallWebApi di esempio.

DELETE (DeleteAsync) e metodi di estensione aggiuntivi

System.Net.Http include metodi di estensione aggiuntivi per l'invio di richieste HTTP e la ricezione di risposte HTTP. HttpClient.DeleteAsync viene usato per inviare una richiesta HTTP DELETE a un'API Web.

Nel codice del componente seguente l'elemento <button> chiama il DeleteItem metodo . L'elemento associato <input> fornisce l'oggetto id dell'elemento da eliminare.

await Http.DeleteAsync($"todoitems/{id}");

Denominato HttpClient con IHttpClientFactory

IHttpClientFactory sono supportati i servizi e la configurazione di un oggetto denominato HttpClient .

Nota

Un'alternativa all'uso di un oggetto denominato HttpClient da un IHttpClientFactory oggetto consiste nell'usare un oggetto tipizzato HttpClient. Per altre informazioni, vedere la sezione Tipizzata HttpClient .

Aggiungere il Microsoft.Extensions.Http pacchetto NuGet all'app.

Nota

Per indicazioni sull'aggiunta di pacchetti alle app .NET, vedere gli articoli sotto Installare e gestire pacchetti in Flusso di lavoro dell'utilizzo di pacchetti (documentazione di NuGet). Confermare le versioni corrette del pacchetto all'indirizzo NuGet.org.

Program Nel file di un progetto client:

builder.Services.AddHttpClient("WebAPI", client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

Se il client denominato deve essere usato dai componenti lato client prerenderati di un Blazor Web Appoggetto , la registrazione del servizio precedente deve essere visualizzata sia nel progetto server che nel progetto..Client Nel server viene builder.HostEnvironment.BaseAddress sostituito dall'indirizzo di base dell'API Web, descritto più avanti.

L'esempio sul lato client precedente imposta l'indirizzo di base con builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), che ottiene l'indirizzo di base per l'app lato client ed è in genere derivato dal <base> valore del href tag nella pagina host.

I casi d'uso più comuni per l'uso dell'indirizzo di base del client sono:

  • Il progetto client (.Client) di un Blazor Web App oggetto che effettua chiamate API Web dai componenti WebAssembly/Auto o dal codice eseguito nel client in WebAssembly alle API nell'app server con lo stesso indirizzo host.
  • Progetto client (Client) di un'app ospitata Blazor WebAssembly che effettua chiamate API Web al progetto server (Server).

Il caso d'uso più comune per l'uso del proprio indirizzo di base del client è nel progetto client (Client) di un'app ospitata Blazor WebAssembly che effettua chiamate API Web al progetto server (Server).

Se si chiama un'API Web esterna (non nello stesso spazio URL dell'app client) o si configurano i servizi in un'app lato server (ad esempio per gestire la pre-gestione dei componenti lato client nel server), impostare l'URI sull'indirizzo di base dell'API Web. L'esempio seguente imposta l'indirizzo di base dell'API Web su https://localhost:5001, in cui un'app per le API Web separata è in esecuzione e pronta per rispondere alle richieste dall'app client:

builder.Services.AddHttpClient("WebAPI", client => 
    client.BaseAddress = new Uri("https://localhost:5001"));

Nel codice del componente seguente:

  • Un'istanza di IHttpClientFactory crea un oggetto denominato HttpClient.
  • Il denominato HttpClient viene usato per emettere una richiesta GET per i dati delle previsioni meteo JSON dall'API Web all'indirizzo /forecast.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        var client = ClientFactory.CreateClient("WebAPI");

        forecasts = await client.GetFromJsonAsync<Forecast[]>("forecast") ?? [];
    }
}

L'app BlazorWebAppCallWebApi di esempio illustra la chiamata di un'API Web con un denominato HttpClient nel relativo CallTodoWebApiCsrNamedClient componente. Per una dimostrazione di lavoro aggiuntiva in un'app client basata sulla chiamata a Microsoft Graph con un denominato HttpClient, vedere Usare l'API Graph con ASP.NET Core Blazor WebAssembly.

Per una dimostrazione funzionante in un'app client basata sulla chiamata a Microsoft Graph con un denominato HttpClient, vedere Usare l'API Graph con ASP.NET Core Blazor WebAssembly.

Digitato HttpClient

Tipizzato HttpClient usa una o più istanze dell'app HttpClient , predefinita o denominata, per restituire dati da uno o più endpoint API Web.

Nota

Un'alternativa all'uso di un tipizzato HttpClient consiste nell'usare un oggetto denominato HttpClient da un oggetto IHttpClientFactory. Per altre informazioni, vedere la sezione Named HttpClient with IHttpClientFactory .

Aggiungere il Microsoft.Extensions.Http pacchetto NuGet all'app.

Nota

Per indicazioni sull'aggiunta di pacchetti alle app .NET, vedere gli articoli sotto Installare e gestire pacchetti in Flusso di lavoro dell'utilizzo di pacchetti (documentazione di NuGet). Confermare le versioni corrette del pacchetto all'indirizzo NuGet.org.

L'esempio seguente invia una richiesta GET per i dati delle previsioni meteo JSON dall'API Web all'indirizzo /forecast.

ForecastHttpClient.cs:

using System.Net.Http.Json;

namespace BlazorSample.Client;

public class ForecastHttpClient(HttpClient http)
{
    public async Task<Forecast[]> GetForecastAsync() => 
        await http.GetFromJsonAsync<Forecast[]>("forecast") ?? [];
}

Program Nel file di un progetto client:

builder.Services.AddHttpClient<ForecastHttpClient>(client => 
    client.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress));

Se il client tipizzato deve essere usato dai componenti lato client prerenderati di un Blazor Web App, la registrazione del servizio precedente deve essere visualizzata sia nel progetto server che nel progetto..Client Nel server viene builder.HostEnvironment.BaseAddress sostituito dall'indirizzo di base dell'API Web, descritto più avanti.

L'esempio precedente imposta l'indirizzo di base con builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), che ottiene l'indirizzo di base per l'app lato client ed è in genere derivato dal <base> valore del href tag nella pagina host.

I casi d'uso più comuni per l'uso dell'indirizzo di base del client sono:

  • Il progetto client (.Client) di un Blazor Web App oggetto che effettua chiamate API Web dai componenti WebAssembly/Auto o dal codice eseguito nel client in WebAssembly alle API nell'app server con lo stesso indirizzo host.
  • Progetto client (Client) di un'app ospitata Blazor WebAssembly che effettua chiamate API Web al progetto server (Server).

Il caso d'uso più comune per l'uso del proprio indirizzo di base del client è nel progetto client (Client) di un'app ospitata Blazor WebAssembly che effettua chiamate API Web al progetto server (Server).

Se si chiama un'API Web esterna (non nello stesso spazio URL dell'app client) o si configurano i servizi in un'app lato server (ad esempio per gestire la pre-gestione dei componenti lato client nel server), impostare l'URI sull'indirizzo di base dell'API Web. L'esempio seguente imposta l'indirizzo di base dell'API Web su https://localhost:5001, in cui un'app per le API Web separata è in esecuzione e pronta per rispondere alle richieste dall'app client:

builder.Services.AddHttpClient<ForecastHttpClient>(client => 
    client.BaseAddress = new Uri("https://localhost:5001"));

I componenti inserisce l'oggetto tipizzato HttpClient per chiamare l'API Web.

Nel codice del componente seguente:

  • Viene inserita un'istanza del precedente ForecastHttpClient , che crea un oggetto tipizzato HttpClient.
  • Il tipo viene HttpClient usato per emettere una richiesta GET per i dati delle previsioni meteo JSON dall'API Web.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

    protected override async Task OnInitializedAsync()
    {
        forecasts = await Http.GetForecastAsync();
    }
}

L'app BlazorWebAppCallWebApi di esempio illustra la chiamata di un'API Web con un tipo nel HttpClient relativo CallTodoWebApiCsrTypedClient componente. Si noti che il componente adotta e il rendering lato client (CSR) (InteractiveWebAssembly modalità di rendering) con pre-esecuzione del provisioning, quindi la registrazione del servizio client tipizzata viene visualizzata nel Program file del progetto server e del .Client progetto.

Le indicazioni contenute in questa sezione si applicano agli scenari lato client che si basano su un'autenticazione cookie.

Per cookiel'autenticazione basata su , considerata più sicura dell'autenticazione del token di connessione, cookie le credenziali possono essere inviate con ogni richiesta api Web chiamando AddHttpMessageHandler con un DelegatingHandler in un oggetto preconfigurato HttpClient. Il gestore configura SetBrowserRequestCredentials con BrowserRequestCredentials.Include, che consiglia al browser di inviare le credenziali con ogni richiesta, ad esempio cookie o intestazioni di autenticazione HTTP, incluse le richieste tra le origini.

CookieHandler.cs:

public class CookieHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
        request.Headers.Add("X-Requested-With", ["XMLHttpRequest"]);

        return base.SendAsync(request, cancellationToken);
    }
}

L'oggetto CookieHandler è registrato nel Program file :

builder.Services.AddTransient<CookieHandler>();

Il gestore messaggi viene aggiunto a qualsiasi preconfigurato HttpClient che richiede cookie l'autenticazione:

builder.Services.AddHttpClient(...)
    .AddHttpMessageHandler<CookieHandler>();

Quando si compone un oggetto HttpRequestMessage, impostare direttamente le credenziali e l'intestazione della richiesta del browser:

var requestMessage = new HttpRequestMessage() { ... };

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
requestMessage.Headers.Add("X-Requested-With", ["XMLHttpRequest"]);

HttpClient e HttpRequestMessage con le opzioni di richiesta dell'API Fetch

Le indicazioni contenute in questa sezione si applicano agli scenari lato client che si basano sull'autenticazione del token di connessione.

HttpClient (documentazione dell'API) e HttpRequestMessage può essere usato per personalizzare le richieste. Ad esempio, è possibile specificare il metodo HTTP e le intestazioni della richiesta. Il componente seguente effettua una POST richiesta a un endpoint API Web e mostra il corpo della risposta.

TodoRequest.razor:

@page "/todo-request"
@using System.Net.Http.Headers
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient Http
@inject IAccessTokenProvider TokenProvider

<h1>ToDo Request</h1>

<h1>ToDo Request Example</h1>

<button @onclick="PostRequest">Submit POST request</button>

<p>Response body returned by the server:</p>

<p>@responseBody</p>

@code {
    private string? responseBody;

    private async Task PostRequest()
    {
        var requestMessage = new HttpRequestMessage()
        {
            Method = new HttpMethod("POST"),
            RequestUri = new Uri("https://localhost:10000/todoitems"),
            Content =
                JsonContent.Create(new TodoItem
                {
                    Name = "My New Todo Item",
                    IsComplete = false
                })
        };

        var tokenResult = await TokenProvider.RequestAccessToken();

        if (tokenResult.TryGetToken(out var token))
        {
            requestMessage.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", token.Value);

            requestMessage.Content.Headers.TryAddWithoutValidation(
                "x-custom-header", "value");

            var response = await Http.SendAsync(requestMessage);
            var responseStatusCode = response.StatusCode;

            responseBody = await response.Content.ReadAsStringAsync();
        }
    }

    public class TodoItem
    {
        public long Id { get; set; }
        public string? Name { get; set; }
        public bool IsComplete { get; set; }
    }
}

BlazorL'implementazione lato client di HttpClient usa l'API Fetch e configura le opzioni dell'API fetch specifiche della richiesta sottostanti tramite HttpRequestMessage metodi di estensione e WebAssemblyHttpRequestMessageExtensions. Impostare opzioni aggiuntive usando il metodo di estensione generico SetBrowserRequestOption . Blazor e l'API Fetch sottostante non aggiungono o modificano direttamente le intestazioni della richiesta. Per altre informazioni sul modo in cui gli agenti utente, ad esempio i browser, interagiscono con le intestazioni, vedere set di documentazione dell'agente utente esterno e altre risorse Web.

La risposta HTTP viene in genere memorizzata nel buffer per abilitare il supporto per le letture sincrone sul contenuto della risposta. Per abilitare il supporto per il flusso di risposte, usare il SetBrowserResponseStreamingEnabled metodo di estensione nella richiesta.

Per includere le credenziali in una richiesta tra origini, usare il metodo di SetBrowserRequestCredentials estensione:

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Per altre informazioni sulle opzioni dell'API Fetch, vedere La documentazione Web MDN: WindowOrWorkerGlobalScope.fetch(): Parameters.

Gestione degli errori

Gestire gli errori di risposta dell'API Web nel codice dello sviluppatore quando si verificano. Ad esempio, GetFromJsonAsync prevede una risposta JSON dall'API Web con un Content-Type di application/json. Se la risposta non è in formato JSON, la convalida del contenuto genera un'eccezione NotSupportedException.

Nell'esempio seguente l'endpoint URI per la richiesta di dati delle previsioni meteo viene digitato in modo non corretto. L'URI deve essere a WeatherForecast ma viene visualizzato nella chiamata come WeatherForcast, che manca la lettera e in Forecast.

La GetFromJsonAsync chiamata prevede la restituzione di JSON, ma l'API Web restituisce HTML per un'eccezione non gestita con un Content-Type valore di text/html. L'eccezione non gestita si verifica perché il percorso di /WeatherForcast non viene trovato e il middleware non può gestire una pagina o una visualizzazione per la richiesta.

In OnInitializedAsync nel client viene NotSupportedException generata quando il contenuto della risposta viene convalidato come non JSON. L'eccezione viene intercettata nel blocco, in cui la catch logica personalizzata potrebbe registrare l'errore o presentare un messaggio di errore descrittivo all'utente.

ReturnHTMLOnException.razor:

@page "/return-html-on-exception"
@using {PROJECT NAME}.Shared
@inject HttpClient Http

<h1>Fetch data but receive HTML on unhandled exception</h1>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <h2>Temperatures by Date</h2>

    <ul>
        @foreach (var forecast in forecasts)
        {
            <li>
                @forecast.Date.ToShortDateString():
                @forecast.TemperatureC &#8451;
                @forecast.TemperatureF &#8457;
            </li>
        }
    </ul>
}

<p>
    @exceptionMessage
</p>

@code {
    private WeatherForecast[]? forecasts;
    private string? exceptionMessage;

    protected override async Task OnInitializedAsync()
    {
        try
        {
            // The URI endpoint "WeatherForecast" is misspelled on purpose on the 
            // next line. See the preceding text for more information.
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForcast");
        }
        catch (NotSupportedException exception)
        {
            exceptionMessage = exception.Message;
        }
    }
}

Nota

L'esempio precedente è a scopo dimostrativo. È possibile configurare un'API Web per restituire JSON anche quando un endpoint non esiste o si verifica un'eccezione non gestita nel server.

Per altre informazioni, vedere Gestire gli errori nelle app ASP.NET CoreBlazor.

Cross-Origin Resource Sharing (CORS)

La sicurezza del browser impedisce a una pagina Web di effettuare richieste a un dominio diverso da quello che ha servito la pagina Web. Questa restrizione è nota come criteri di corrispondenza dell'origine. I criteri di stessa origine limitano (ma non impediscono) a un sito dannoso di leggere i dati sensibili da un altro sito. Per effettuare richieste dal browser a un endpoint con un'origine diversa, l'endpoint deve abilitare la condivisione di risorse tra le origini (CORS).

Per altre informazioni su CORS sul lato server, vedere Abilitare le richieste tra le origini (CORS) in ASP.NET Core. Gli esempi dell'articolo non riguardano direttamente Razor gli scenari dei componenti, ma l'articolo è utile per apprendere concetti CORS generali.

Per informazioni sulle richieste CORS sul lato client, vedere ASP.NET Scenari di sicurezza aggiuntivi coreBlazor WebAssembly.

Supporto antiforgerato

Per aggiungere il supporto antiforgery a una richiesta HTTP, inserire AntiforgeryStateProvider e aggiungere un RequestToken alla raccolta di intestazioni come RequestVerificationToken:

@inject AntiforgeryStateProvider Antiforgery
private async Task OnSubmit()
{
    var antiforgery = Antiforgery.GetAntiforgeryToken();
    var request = new HttpRequestMessage(HttpMethod.Post, "action");
    request.Headers.Add("RequestVerificationToken", antiforgery.RequestToken);
    var response = await client.SendAsync(request);
    ...
}

Per altre informazioni, vedere autenticazione e autorizzazione di base ASP.NETBlazor.

Blazor Esempi di componenti framework per il test dell'accesso all'API Web

Vari strumenti di rete sono disponibili pubblicamente per testare direttamente le app back-end dell'API Web, ad esempio Firefox Browser Developer. Blazor L'origine di riferimento del framework include HttpClient asset di test utili per i test:

HttpClientTest asset nel dotnet/aspnetcore repository GitHub

Nota

I collegamenti della documentazione all'origine del riferimento .NET in genere caricano il ramo predefinito del repository, che rappresenta lo sviluppo corrente per la versione successiva di .NET. Per selezionare un tag per una versione specifica, usare l'elenco a discesa Switch branches or tags. Per altre informazioni, vedere How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Come selezionare un tag di versione del codice sorgente di ASP.NET - dotnet/AspNetCore.Docs #26205).

Risorse aggiuntive

Generali

Mitigazione degli attacchi di overposting

Le API Web possono essere vulnerabili a un attacco di overposting , noto anche come attacco di assegnazione di massa. Un attacco di overposting si verifica quando un utente malintenzionato rilascia un POST in formato HTML al server che elabora i dati per le proprietà che non fanno parte del modulo sottoposto a rendering e che lo sviluppatore non vuole consentire agli utenti di modificare. Il termine "overposting" significa letteralmente che l'utente malintenzionato ha over-POSTed con il modulo.

Per indicazioni sulla mitigazione degli attacchi di overposting, vedere Esercitazione: Creare un'API Web con ASP.NET Core.

Lato server

Lato client