Partager via


Appeler une API web à partir d’ASP.NET Core Blazor

Note

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Avertissement

Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la Stratégie de prise en charge de .NET et .NET Core. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Cet article explique comment appeler une API web à partir d’une application Blazor.

Package

Le package System.Net.Http.Json fournit des méthodes d’extension pour System.Net.Http.HttpClient et System.Net.Http.HttpContent qui effectuent la sérialisation et la désérialisation automatiques à l’aide de System.Text.Json. Le package System.Net.Http.Json est fourni par le framework partagé .NET et ne nécessite pas l’ajout d’une référence de package à l’application.

Exemples d’applications

Consultez les exemples d’application dans le dépôt GitHub dotnet/blazor-samples.

BlazorWebAppCallWebApi

Appelez une API web de liste de tâches externe (pas dans l’Blazor Web App) depuis une Blazor Web App :

  • Backend : une application API web pour la gestion d’une liste de tâches, basée sur des API minimales. L’application API web est une application distincte de l’Blazor Web App, éventuellement hébergée sur un autre serveur.
  • BlazorApp/BlazorApp.Client : une Blazor Web App qui appelle l’application API web avec un HttpClient pour les opérations de la liste de tâches, comme la création, la lecture, la mise à jour et la suppression (CRUD) d’éléments dans la liste de tâches.

Pour le rendu côté client, qui inclut des composants WebAssembly interactifs et des composants Auto qui ont adopté le rendu côté client, les appels sont effectués avec un HttpClient préconfiguré inscrit dans le fichier Program du projet client (BlazorApp.Client) :

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

Pour le rendu côté serveur, qui inclut des composants serveur prérendus et interactifs, des composants WebAssembly prérendus et des composants Auto qui sont prérendus ou qui ont adopté le rendu côté serveur, les appels sont effectués avec un HttpClient inscrit dans le fichier Program du projet serveur (BlazorApp) :

builder.Services.AddHttpClient();

Appelez une API de liste de films interne (dans l’Blazor Web App), où l’API se trouve dans le projet serveur de l’Blazor Web App :

  • BlazorApp : une Blazor Web App qui gère une liste de films :
    • Quand des opérations sont effectuées sur la liste de films dans l’application sur le serveur, des appels d’API ordinaires sont utilisés.
    • Quand des appels d’API sont effectués par un client web, une API web est utilisée pour les opérations de la liste de films, basées sur des API minimales.
  • BlazorApp.Client : le projet client de l’Blazor Web App, qui contient des composants WebAssembly interactifs et Auto pour la gestion des utilisateurs de la liste de films.

Pour le rendu côté client, qui inclut des composants WebAssembly interactifs et des composants Auto qui ont adopté le rendu côté client, les appels à l’API sont effectués via un service basé sur le client (ClientMovieService) qui utilise un HttpClient préconfiguré inscrit dans le fichier Program du projet client (BlazorApp.Client). Comme ces appels sont effectués sur un site web public ou privé, l’API de liste de films est une API web.

L’exemple suivant obtient une liste de films à partir du point de terminaison /movies :

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

Pour le rendu côté serveur, qui inclut des composants serveur prérendus et interactifs, des composants WebAssembly prérendus et des composants Auto qui sont prérendus ou qui ont adopté le rendu côté serveur, les appels sont effectués directement via un service basé sur le serveur (ServerMovieService). L’API ne s’appuie pas sur un réseau : c’est donc une API standard pour les opérations CRUD de la liste de films.

L’exemple suivant obtient une liste de films :

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 exemple d’application de données météorologiques qui utilise le rendu de diffusion en continu pour des données météorologiques.

BlazorWebAssemblyCallWebApi

Appelle une API web de liste de tâches depuis une application Blazor WebAssembly :

  • Backend : une application API web pour la gestion d’une liste de tâches, basée sur des API minimales.
  • BlazorTodo: une application Blazor WebAssembly qui appelle l’API web avec un HttpClient préconfiguré pour les opérations CRUD de la liste de tâches.

Scénarios côté serveur pour l’appel d’API web externes

Les composants basés sur le serveur appellent des API web externes en utilisant des instances HttpClient, généralement créées avec IHttpClientFactory. Pour obtenir des conseils qui s’appliquent aux applications côté serveur, consultez Effectuer des requêtes HTTP en utilisant IHttpClientFactory dans ASP.NET Core.

Une application côté serveur n’inclut pas de service HttpClient. Fournissez un HttpClient à l’application à l’aide du framework de fabrique HttpClient.

Dans le fichier Program :

builder.Services.AddHttpClient();

Le composant Razor suivant effectue une requête auprès d’une API web pour les branches GitHub, comme dans l’exemple d’Utilisation de base de l’article Effectuer des requêtes HTTP en utilisant IHttpClientFactory dans 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; }
    }
}

Dans l’exemple précédent pour C# 12 ou ultérieur, un tableau vide ([]) est créé pour la variable branches. Pour les versions antérieures de C#, créez un tableau vide (Array.Empty<GitHubBranch>()).

Pour obtenir un exemple de travail supplémentaire, consultez l’exemple de chargement de fichiers côté serveur qui charge des fichiers sur un contrôleur d’API web dans l’article Chargements de fichiersBlazor ASP.NET Core.

Abstractions de service pour les appels d’API web

Cette section s’applique aux applications Blazor Web App qui gèrent une API web dans le projet serveur ou transforment les appels d’API web en API web externe.

Lors de l’utilisation des modes de rendu WebAssembly interactif et Auto, les composants sont prérendus par défaut. Les composants Auto sont également initialement rendus de façon interactive depuis le serveur avant le téléchargement du pack Blazor sur le client et avant que le runtime côté client s’active. Cela signifie que les composants utilisant ces modes de rendu doivent être conçus de façon à s’exécuter correctement depuis le client et depuis le serveur. Si le composant doit appeler une API basée sur un projet serveur ou transformer une requête en API web externe (une en dehors de l’Blazor Web App) lors de l’exécution sur le client, l’approche recommandée consiste à abstraire cet appel d’API derrière une interface de service, et à implémenter les versions client et serveur du service :

  • La version client appelle l’API web avec un HttpClientpréconfiguré.
  • La version serveur peut généralement accéder directement aux ressources côté serveur. L’injection d’un HttpClient sur le serveur qui effectue des appels vers le serveur n’est pas recommandée, la requête réseau n’étant généralement pas nécessaire. L’API peut également être externe au projet de serveur, mais une abstraction de service pour le serveur est nécessaire pour transformer la requête d’une certaine manière, par exemple pour ajouter un jeton d’accès à une requête proxisée.

Quand vous utilisez le mode de rendu WebAssembly, vous avez également la possibilité de désactiver le prérendu : les composants sont alors rendus seulement depuis le client. Pour plus d’informations, consultez Modes de rendu ASP.NET Core Blazor.

Exemples (exemples d’applications) :

  • API web de liste de films dans l’exemple d’application BlazorWebAppCallWebApi.
  • API web de rendu en diffusion en continu de données météorologiques dans l’exemple d’application BlazorWebAppCallWebApi_Weather.
  • Données météo retournées au client dans les exemples d’applications BlazorWebAppOidc (modèle non-BFF) ou BlazorWebAppOidcBff (modèle BFF). Ces applications illustrent des appels d’API (web) sécurisés. Pour plus d’informations, consultez Sécuriser une Blazor Web App ASP.NET Core avec OpenID Connect (OIDC).

API web externes Blazor Web App

Cette section s’applique aux Blazor Web App qui appellent une API web gérée par un projet distinct (externe), éventuellement hébergé sur un autre serveur.

Les Blazor Web App prérendent normalement les composants WebAssembly côté client, et le rendu des composants Auto s’effectue sur le serveur pendant le rendu statique ou interactif côté serveur (SSR). Les services HttpClient ne sont pas inscrits par défaut dans le projet principal d’une Blazor Web App. Si l’application est exécutée uniquement avec les services HttpClient inscrits dans le projet .Client, comme décrit dans la section Ajout du service HttpClient, l’exécution de l’application entraîne une erreur d’exécution :

InvalidOperationException : Impossible de fournir une valeur à la propriété « Http » sur un type « ...{COMPONENT} ». Il n’existe aucun service inscrit de type « System.Net.Http.HttpClient ».

Utilisez l’une des approches suivantes :

  • Ajoutez les services HttpClient au projet serveur pour rendre HttpClient disponible lors du rendu côté serveur. Utilisez l’inscription de service suivante dans le fichier Program du projet serveur :

    builder.Services.AddHttpClient();
    

    Les services HttpClient sont fournis par l’infrastructure partagée. Par conséquent, une référence de package dans le fichier de projet de l’application n’est pas nécessaire.

    Exemple : API web de liste de tâches dans l’exemple d’application BlazorWebAppCallWebApi

  • Si le prérendu n’est pas requis pour un composant WebAssembly qui appelle l’API web, désactivez-le en suivant l’aide fournie dans Modes de rendu Blazor d’ASP.NET Core. Si vous adoptez cette approche, vous n’avez pas besoin d’ajouter de services HttpClient au projet principal de l’Blazor Web App, car le composant n’est pas prérendu sur le serveur.

Pour plus d’informations, consultez Échec de la résolution des services côté client lors du prérendu.

Données prérendues

Lors du prérendu, les composants sont rendus deux fois : d’abord de façon statique, puis de façon interactive. L’état ne passe pas automatiquement du composant prérendu au composant interactif. Si un composant effectue des opérations d’initialisation asynchrones et rend un contenu différent pour différents états lors de l’initialisation, par exemple un indicateur de progression « Chargement... », vous pouvez voir un scintillement quand le composant est rendu deux fois.

Vous pouvez résoudre ce problème en passant l’état prérendu à l’aide de l’API État de composant persistant, ce qui est montré par les exemples d’applications BlazorWebAppCallWebApi et BlazorWebAppCallWebApi_Weather. Quand le composant est rendu de façon interactive, il peut être rendu de la même façon en utilisant le même état. Cependant, l’API ne fonctionne actuellement pas avec une navigation améliorée, ce que vous pouvez contourner en désactivant la navigation améliorée sur les liens vers la page (data-enhanced-nav=false). Pour plus d’informations, consultez les ressources suivantes :

Ajouter le service HttpClient

L’aide fournie dans cette section s’applique aux scénarios côté client.

Les composants côté client appellent des API web en utilisant un service HttpClient préconfiguré, qui se concentre sur l’envoi de requêtes au serveur d’origine. Des configurations de service HttpClient supplémentaires pour d’autres API web peuvent être créées dans le code du développeur. Les requêtes sont composées à l’aide d’helpers Blazor JSON ou avec HttpRequestMessage. Les requêtes peuvent inclure la configuration de l’option API Fetch.

Les exemples de configuration de cette section ne sont utiles que lorsqu’une API web unique est appelée pour une seule instance HttpClient dans l’application. Lorsque l’application doit appeler plusieurs API web, chacune avec sa propre adresse de base et sa configuration, vous pouvez adopter les approches suivantes, qui sont décrites ultérieurement dans cet article :

  • Nommé HttpClient avec IHttpClientFactory: chaque API web reçoit un nom unique. Quand le code d’application ou un Razor composant appelle une API web, il utilise une instance nommée HttpClient pour effectuer l’appel.
  • Typé HttpClient : chaque API web est typée. Quand le code d’application ou un Razor composant appelle une API web, il utilise une instance typée HttpClient pour effectuer l’appel.

Dans le fichier Program, ajoutez un service HttpClient s’il n’est pas déjà présent à partir d’un modèle de projet Blazor utilisé pour créer l’application :

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

L’exemple précédent définit l’adresse de base avec builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress). Cette propriété récupère l’adresse de base de l’application. Elle est généralement dérivée de la valeur href de la balise <base> dans la page hôte.

Les cas d’usage les plus courants pour l’utilisation de l’adresse de base du client sont les suivants :

  • Le projet client (.Client) d’une application Blazor Web App (.NET 8 ou version ultérieure) effectue des appels d’API web à partir de composants WebAssembly ou d’un code qui s’exécute sur le client dans WebAssembly vers des API de l’application serveur.
  • Le projet client (Client) d’une application hébergée Blazor WebAssembly effectue des appels d’API web vers le projet de serveur (Server). Notez que le modèle de projet hébergé Blazor WebAssembly n’est plus disponible dans .NET 8 ou version ultérieure. Toutefois, les applications hébergées Blazor WebAssembly restent prises en charge pour .NET 8.

Si vous appelez une API web externe (pas dans le même espace d’URL que l’application cliente), définissez l’URI sur l’adresse de base de l’API web. L’exemple suivant définit l’adresse de base de l’API web sur https://localhost:5001, où une application API web distincte est en cours d’exécution et prête à répondre aux demandes de l’application cliente :

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

Helpers JSON

HttpClient est disponible en tant que service préconfiguré pour envoyer des requêtes au serveur d’origine.

HttpClient et les helpers JSON (System.Net.Http.Json.HttpClientJsonExtensions) sont également utilisés pour appeler des points de terminaison d’API web tiers. HttpClient est implémenté à l’aide de l’API Fetch du navigateur et est soumis à ses limitations, y compris l’application de la stratégie de même origine, qui est abordée plus loin dans cet article dans la section Partage de ressources Cross-Origin (CORS).

L’adresse de base du client est définie sur l’adresse du serveur d’origine. Injectez une instance de HttpClient dans un composant à l’aide de la directive @inject :

@using System.Net.Http
@inject HttpClient Http

Utilisez l’espace de noms System.Net.Http.Json pour accéder à HttpClientJsonExtensions, y compris GetFromJsonAsync, PutAsJsonAsync et PostAsJsonAsync :

@using System.Net.Http.Json

Les sections suivantes couvrent les helpers JSON :

System.Net.Http inclut des méthodes supplémentaires pour envoyer des requêtes HTTP et recevoir des réponses HTTP, par exemple pour envoyer une requête DELETE. Pour plus d’informations, consultez la section DELETE et autres méthodes d’extension.

GET à partir de JSON (GetFromJsonAsync)

GetFromJsonAsync envoie une requête HTTP GET et analyse le corps de la réponse JSON pour créer un objet.

Dans le code du composant suivant, les todoItems sont affichés par le composant. GetFromJsonAsync est appelé lorsque l’initialisation du composant est terminée (OnInitializedAsync).

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

POST en tant que JSON (PostAsJsonAsync)

PostAsJsonAsync envoie une requête POST à l’URI spécifié contenant la valeur sérialisée en JSON dans le corps de la requête.

Dans le code de composant suivant, newItemName est fourni par un élément lié du composant. La méthode AddItem est déclenchée en sélectionnant un élément <button>.

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

PostAsJsonAsyncRetourne un HttpResponseMessage. Pour désérialiser le contenu JSON du message de réponse, utilisez la méthode d’extension ReadFromJsonAsync. L’exemple suivant lit les données météorologiques JSON sous forme de tableau :

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

PUT en tant que JSON (PutAsJsonAsync)

PutAsJsonAsync envoie une requête HTTP PUT avec du contenu encodé en JSON.

Dans le code de composant suivant, les valeurs editItem pour Name et IsCompleted sont fournies par des éléments liés du composant. L’élément est défini lorsque l’élément Id est sélectionné dans une autre partie de l’interface utilisateur (non affiché), et EditItem est appelé. La méthode SaveItem est déclenchée en sélectionnant l’élément <button>. L’exemple suivant n’affiche pas le chargement de todoItems pour la concision. Consultez la section GET à partir de JSON (GetFromJsonAsync) pour obtenir un exemple de chargement d’éléments.

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

PutAsJsonAsyncRetourne un HttpResponseMessage. Pour désérialiser le contenu JSON du message de réponse, utilisez la méthode d’extension ReadFromJsonAsync. L’exemple suivant lit les données météorologiques JSON sous forme de tableau :

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

PATCH en tant que JSON (PatchAsJsonAsync)

PatchAsJsonAsync envoie une requête HTTP PATCH avec du contenu encodé en JSON.

Remarque

Pour plus d’informations, consultez JsonPatch dans une API web ASP.NET Core.

Dans l’exemple suivant, PatchAsJsonAsync reçoit un document JSON PATCH sous forme de chaîne de texte brut avec des guillemets d’échappement :

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

PatchAsJsonAsyncRetourne un HttpResponseMessage. Pour désérialiser le contenu JSON du message de réponse, utilisez la méthode d’extension ReadFromJsonAsync. L’exemple suivant lit les données des éléments TODO JSON en tant que tableau. Un tableau vide est créé si aucune donnée n’est retournée par la méthode : content n’est donc pas nul après l’exécution de l’instruction :

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

Mise en forme avec une mise en retrait, des espacements et des guillemets non échappés, le document PATCH apparaît sous la forme du JSON suivant :

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

Pour simplifier la création de documents PATCH dans l’application qui émet des requêtes PATCH, une application peut utiliser la prise en charge de PATCH avec .NET JSON, comme le montre les instructions suivantes.

Installez le package NuGet Microsoft.AspNetCore.JsonPatch et utilisez les fonctionnalités d’API du package pour composer JsonPatchDocument pour une requête PATCH.

Note

Pour obtenir des conseils sur l’ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Ajoutez des directives @using pour les espaces de noms System.Text.Json, System.Text.Json.Serialization et Microsoft.AspNetCore.JsonPatch en haut du composant Razor :

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

Composez JsonPatchDocument pour un TodoItem avec IsComplete défini sur true en utilisant la méthode Replace :

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

Passez les opérations du document (patchDocument.Operations) à l’appel PatchAsJsonAsync :

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

JsonSerializerOptions.DefaultIgnoreCondition est défini à JsonIgnoreCondition.WhenWritingDefault pour ignorer une propriété uniquement si elle est égale à la valeur par défaut de son type.

Ajoutez JsonSerializerOptions.WriteIndented défini sur true si vous voulez afficher la charge utile JSON dans un format d’affichage attractif. L’écriture en retrait du JSON n’a aucune incidence sur le traitement des requêtes PATCH et n’est généralement pas effectuée dans les applications de production pour les requêtes d’API web.

Suivez les instructions dans l’article JsonPatch dans l’API web ASP.NET Core pour ajouter une action de contrôleur PATCH à l’API web. Vous pouvez également implémenter le traitement des requêtes PATCH en tant qu’API minimale en suivant ces étapes.

Ajoutez une référence de package pour le package NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson à l’application API web.

Note

Il n’est pas nécessaire d’ajouter une référence de package pour le package Microsoft.AspNetCore.JsonPatch à l’application, car la référence au packageMicrosoft.AspNetCore.Mvc.NewtonsoftJson ajoute automatiquement une référence de package pour Microsoft.AspNetCore.JsonPatch.

Dans le fichier Program, ajoutez une directive @using pour l’espace de noms Microsoft.AspNetCore.JsonPatch :

using Microsoft.AspNetCore.JsonPatch;

Fournissez le point de terminaison au pipeline de traitement des requêtes de l’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();
});

Avertissement

Comme pour les autres exemples dans l’article JsonPatch dans l’API web ASP.NET Core, l’API PATCH précédente ne protège pas l’API web d’attaques « over-posting ». Pour plus d’informations, consultez Tutoriel : créer une API web avec ASP.NET Core.

Pour une expérience PATCH entièrement opérationnelle, consultez l’exemple d’application BlazorWebAppCallWebApi.

DELETE (DeleteAsync) et autres méthodes d’extension

System.Net.Http inclut des méthodes d’extension supplémentaires pour l’envoi de requêtes HTTP et la réception de réponses HTTP. HttpClient.DeleteAsync est utilisé pour envoyer une requête HTTP DELETE à une API web.

Dans le code de composant suivant, l’élément <button> appelle la méthode DeleteItem. L’élément <input> lié fournit le id de l’élément à supprimer.

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

HttpClient nommé avec IHttpClientFactory

Les services IHttpClientFactory et la configuration d’un HttpClient nommé sont pris en charge.

Note

Une alternative à l’utilisation d’un HttpClient nommé à partir d’un IHttpClientFactory consiste à utiliser un HttpClient typé. Pour plus d’informations, consultez la section HttpClient typé.

Ajoutez le package NuGet Microsoft.Extensions.Http à l’application.

Note

Pour obtenir des conseils sur l’ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

Dans le fichier Program d’un projet client :

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

Si le client nommé doit être utilisé par des composants côté client prérendus d’une Blazor Web App, l’inscription de service précédente devrait apparaître à la fois dans le projet serveur et le projet .Client. Sur le serveur, builder.HostEnvironment.BaseAddress est remplacé par l’adresse de base de l’API web, qui est décrite plus loin.

L’exemple côté client précédent définit l’adresse de base avec builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress). Cette propriété récupère l’adresse de base de l’application côté client. Elle est généralement dérivée de la valeur href de la balise <base> dans la page hôte.

Les cas d’usage les plus courants pour l’utilisation de l’adresse de base du client sont les suivants :

  • Le projet client (.Client) d’une Blazor Web App qui effectue des appels d’API web à partir de composants WebAssembly/Auto ou d’un code qui s’exécute sur le client dans WebAssembly aux API de l’application serveur sur la même adresse hôte.
  • Le projet client (Client) d’une application Blazor WebAssembly hébergée qui effectue des appels d’API web au projet serveur (Server).

Le cas d’usage le plus courant de l’adresse de base du client est dans le projet client (Client) d’une application Blazor WebAssembly hébergée qui effectue des appels d’API web au projet serveur (Server).

Si vous appelez une API web externe (pas dans le même espace d’URL que l’application cliente) ou si vous configurez les services dans une application côté serveur (par exemple, pour traiter le prérendu des composants côté client sur le serveur), définissez l’URI sur l’adresse de base de l’API web. L’exemple suivant définit l’adresse de base de l’API web sur https://localhost:5001, où une application API web distincte est en cours d’exécution et prête à répondre aux demandes de l’application cliente :

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

Dans le composant de code suivant :

  • Une instance de IHttpClientFactory crée un HttpClient nommé.
  • Le HttpClient nommé est utilisé pour émettre une requête GET pour les données de prévision météorologiques JSON à partir de l’API web sur /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’exemple d’application BlazorWebAppCallWebApi illustre l’appel d’une API web avec un HttpClient nommé dans son composant CallTodoWebApiCsrNamedClient. Pour une autre démonstration opérationnelle dans une application cliente basée sur l’appel de Microsoft Graph avec un HttpClient nommé, consultez Utiliser l’API Graph avec ASP.NET Core Blazor WebAssembly.

Pour une démonstration opérationnelle dans une application cliente basée sur l’appel de Microsoft Graph avec un HttpClient nommé, consultez Utiliser l’API Graph avec ASP.NET Core Blazor WebAssembly.

HttpClient typé

Le HttpClient typé utilise une ou plusieurs instances HttpClient de l’application, par défaut ou nommées, pour retourner des données à partir d’un ou plusieurs points de terminaison d’API web.

Note

Une alternative à l’utilisation d’un HttpClient typé consiste à utiliser un HttpClient nommé à partir d’un IHttpClientFactory. Pour plus d’informations, consultez la section HttpClient nommé avec IHttpClientFactory.

Ajoutez le package NuGet Microsoft.Extensions.Http à l’application.

Note

Pour obtenir des conseils sur l’ajout de packages à des applications .NET, consultez les articles figurant sous Installer et gérer des packages dans Flux de travail de la consommation des packages (documentation NuGet). Vérifiez les versions du package sur NuGet.org.

L’exemple suivant émet une requête GET pour les données de prévision météorologiques JSON à partir de l’API web sur /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") ?? [];
}

Dans le fichier Program d’un projet client :

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

Si le client typé doit être utilisé par des composants côté client prérendus d’une Blazor Web App, l’inscription de service précédente devrait apparaître à la fois dans le projet serveur et le projet .Client. Sur le serveur, builder.HostEnvironment.BaseAddress est remplacé par l’adresse de base de l’API web, qui est décrite plus loin.

L’exemple précédent définit l’adresse de base avec builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress). Cette propriété récupère l’adresse de base de l’application côté client. Elle est généralement dérivée de la valeur href de la balise <base> dans la page hôte.

Les cas d’usage les plus courants pour l’utilisation de l’adresse de base du client sont les suivants :

  • Le projet client (.Client) d’une Blazor Web App qui effectue des appels d’API web à partir de composants WebAssembly/Auto ou d’un code qui s’exécute sur le client dans WebAssembly aux API de l’application serveur sur la même adresse hôte.
  • Le projet client (Client) d’une application Blazor WebAssembly hébergée qui effectue des appels d’API web au projet serveur (Server).

Le cas d’usage le plus courant de l’adresse de base du client est dans le projet client (Client) d’une application Blazor WebAssembly hébergée qui effectue des appels d’API web au projet serveur (Server).

Si vous appelez une API web externe (pas dans le même espace d’URL que l’application cliente) ou si vous configurez les services dans une application côté serveur (par exemple, pour traiter le prérendu des composants côté client sur le serveur), définissez l’URI sur l’adresse de base de l’API web. L’exemple suivant définit l’adresse de base de l’API web sur https://localhost:5001, où une application API web distincte est en cours d’exécution et prête à répondre aux demandes de l’application cliente :

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

Les composants injectent le HttpClient typé pour appeler l’API web.

Dans le composant de code suivant :

  • Une instance du ForecastHttpClient précédent est injectée, ce qui crée un HttpClient typé.
  • Le HttpClient typé est utilisé pour émettre une requête GET pour les données de prévision météorologiques JSON à partir de l’API web.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

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

L’exemple d’application BlazorWebAppCallWebApi illustre l’appel d’une API web avec un HttpClient typé dans son composant CallTodoWebApiCsrTypedClient. Notez que le composant adopte le rendu côté client (CSR) (mode de rendu InteractiveWebAssembly) avec prérendu, de sorte que l’inscription de service client typée apparaît dans le fichier Program du projet serveur et du projet .Client.

Les conseils de cette section s’appliquent aux scénarios côté client qui s’appuient sur une authentification cookie.

Pour l’authentification basée sur cookie, considérée comme plus sécurisée que l’authentification par jeton du porteur, cookie informations d’identification peuvent être envoyées avec chaque requête d’API web en appelant AddHttpMessageHandler avec un DelegatingHandler sur un HttpClientpréconfiguré. Le gestionnaire configure SetBrowserRequestCredentials avec BrowserRequestCredentials.Include, qui communique au navigateur d’envoyer des informations d’identification avec chaque requête, comme les cookies ou les en-têtes d’authentification HTTP, y compris pour les requêtes inter-origines.

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

Le CookieHandler est inscrit dans le ficher Program :

builder.Services.AddTransient<CookieHandler>();

Le gestionnaire de messages est ajouté à toute HttpClient préconfigurée qui nécessite l’authentification cookie :

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

Lors de la composition d’un HttpRequestMessage, définissez directement les informations d’identification et l’en-tête de la requête de navigateur :

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

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

HttpClient et HttpRequestMessage avec des options de requête d’API Fetch

L’aide fournie dans cette section s’applique aux scénarios côté client qui reposent sur une authentification par jeton du porteur.

HttpClient (documentation de l’API) et HttpRequestMessage peuvent être utilisés pour personnaliser les requêtes. Par exemple, vous pouvez spécifier la méthode HTTP et les en-têtes de requête. Le composant suivant effectue une requête POST sur un point de terminaison d’API web et affiche le corps de la réponse.

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

L’implémentation de HttpClient du côté du client de Blazor utilise l’API Fetch et configure les options de l’API Fetch spécifiques à la requête sous-jacentes par les méthodes d’extension HttpRequestMessage et par WebAssemblyHttpRequestMessageExtensions. Définissez des options supplémentaires à l’aide de la méthode d’extension générique SetBrowserRequestOption. Blazor et l’API Fetch sous-jacente n’ajoutent ou ne modifient pas directement les en-têtes de demande. Pour plus d’informations sur la façon dont les agents utilisateur (comme les navigateurs) interagissent avec les en-têtes, consultez la documentation complète sur de l’agent utilisateur externe et d’autres ressources web.

La réponse HTTP est généralement mise en mémoire tampon pour activer la prise en charge des lectures synchrones sur le contenu de la réponse. Pour activer la prise en charge de la diffusion en continu des réponses, utilisez la méthode d’extension SetBrowserResponseStreamingEnabled sur la requête.

Pour inclure des informations d’identification dans une requête cross-origin, utilisez la méthode d’extension SetBrowserRequestCredentials :

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Pour plus d’informations sur les options de l’API Fetch, consultez Documents web MDN : WindowOrWorkerGlobalScope.fetch() : Paramètres.

Gérer les erreurs

Gérez les erreurs de réponse de l’API web dans le code du développeur lorsqu’elles se produisent. Par exemple, GetFromJsonAsync attend une réponse JSON de l’API web avec un Content-Type application/json. Si la réponse n’est pas au format JSON, la validation du contenu renvoie une exception NotSupportedException.

Dans l’exemple suivant, le point de terminaison d’URI pour la requête de données de prévision météorologique est mal orthographié. L’URI doit être WeatherForecast, mais apparaît dans l’appel sous la forme WeatherForcast, la lettre e manquant dans Forecast.

L’appel GetFromJsonAsync s’attend à ce que du JSON soit renvoyé, mais l’API web renvoie du code HTML pour une exception non prise en charge avec un Content-Type text/html. L’exception non gérée se produit car le chemin d’accès à /WeatherForcast est introuvable et l’intergiciel ne peut pas servir une page ou une vue pour la requête.

Dans le OnInitializedAsync du client, une exception NotSupportedException est renvoyée lorsque le contenu de la réponse est validée comme non-JSON. L’exception est interceptée dans le bloc catch, où une logique personnalisée peut consigner l’erreur ou présenter un message d’erreur convivial à l’utilisateur.

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

Note

L’exemple précédent est fourni à des fins de démonstration. Une API web peut être configurée pour renvoyer du JSON même quand un point de terminaison n’existe pas ou qu’une exception non prise en charge se produit sur le serveur.

Pour plus d’informations, consultez Gérer les erreurs dans les applications ASP.NET Core Blazor.

CORS (Cross Origin Resource Sharing)

La sécurité du navigateur empêche une page web d’envoyer des requêtes à un domaine différent de celui qui a servi la page web. Cette restriction est appelée stratégie de même origine. La stratégie de même origine restreint (mais n’empêche pas) un site malveillant de lire des données sensibles à partir d’un autre site. Pour effectuer des requêtes à partir du navigateur vers un point de terminaison avec une origine différente, le point de terminaison doit activer le partage de ressources Cross-Origin (CORS).

Pour plus d’informations sur CORS côté serveur, consultez Activer les requêtes multi-origines (CORS) dans ASP.NET Core. Les exemples de l’article ne concernent pas directement les scénarios du composant Razor, mais l’article est utile pour apprendre les concepts généraux de CORS.

Pour plus d’informations sur les requêtes CORS côté client, consultez Scénarios de sécurité supplémentaires ASP.NET CoreBlazor WebAssembly.

Prise en charge d’Antiforgery

Pour ajouter la prise en charge Antiforgery à une requête HTTP, injectez AntiforgeryStateProvider ajoutez-en-tête RequestToken à la collection d’en-têtes en tant que 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);
    ...
}

Pour plus d’informations, consultez Authentification et autorisationBlazor ASP.NET Core .

Exemples de composants de framework Blazor pour tester l’accès à l’API web

Différents outils réseau sont disponibles publiquement pour tester directement les applications back-ends d’API web, comme Firefox Browser Developer. La source de référence du framework Blazor inclut des ressources de test HttpClient utiles pour tester :

Ressources HttpClientTest dans le dépôt GitHub dotnet/aspnetcore

Note

Les liens de documentation vers la source de référence .NET chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment sélectionner une balise de version du code source ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Ressources supplémentaires

Général

Atténuation des attaques par surcharge POST

Les API web peuvent être vulnérables à une attaque par surcharge POST, également appelée attaque par affectation en masse. Une attaque par surcharge POST se produit quand un utilisateur malveillant soumet un formulaire HTML via la méthode POST au serveur de traitement des données, en ajoutant des données correspondant à des propriétés qui ne font pas partie du formulaire affiché, et que le développeur ne souhaite pas que les utilisateurs modifient. L’expression « surcharge POST » signifie littéralement que l’utilisateur malveillant a surchargé le formulaire de données POST.

Pour obtenir des conseils sur l’atténuation des attaques par surcharge POST, consultez Tutoriel : créer une API web avec ASP.NET Core.

Côté serveur

Côté client