Aufrufen einer Web-API über ASP.NET Core Blazor

Hinweis

Dies ist nicht die neueste Version dieses Artikels. Informationen zum aktuellen Release finden Sie in der ASP.NET Core 8.0-Version dieses Artikels.

In diesem Artikel wird erläutert, wie Sie eine Web-API über eine Blazor-App aufrufen.

Paket

Das Paket System.Net.Http.Json stellt Erweiterungsmethoden für System.Net.Http.HttpClient und System.Net.Http.HttpContent bereit, die die automatische Serialisierung und Deserialisierung mit System.Text.Json ausführen. Das Paket System.Net.Http.Json wird vom freigegebenen .NET Framework bereitgestellt und erfordert nicht, dass ein Paketverweis zur App hinzugefügt wird.

Beispiel-Apps

Die Beispiel-Apps finden Sie im GitHub-Repository dotnet/blazor-samples.

BlazorWebAppCallWebApi

Rufen Sie eine externe (nicht in der Blazor-Web-App) Aufgabenlisten-Web-API aus einer Blazor-Web-App auf:

  • Backend: Eine Web-API-App basierend auf Minimal-APIs zum Verwalten einer Aufgabenliste. Die Web-API-App ist eine andere App als die Blazor-Web-App, die möglicherweise auf einem anderen Server gehostet wird.
  • BlazorApp/BlazorApp.Client: Eine Blazor-Web-App, die die Web-API-App mit HttpClient für Aufgabenlistenvorgänge aufruft, z. B. Erstellen, Lesen, Aktualisieren und Löschen (CRUD) von Elementen aus der Aufgabenliste

Bei clientseitigem Rendering (CSR), das interaktive WebAssembly-Komponenten und Autokomponenten umfasst, bei denen CSR verwendet wird, werden Aufrufe mit HttpClient (vorkonfiguriert) durchgeführt, was in der Program-Datei des Clientprojekts (BlazorApp.Client) registriert ist:

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

Bei serverseitigem Rendering (SSR), das vorab gerenderte und interaktive Serverkomponenten, vorab gerenderte WebAssembly-Komponenten und Autokomponenten umfasst, die vorab gerendert oder SSR verwenden, werden Aufrufe mit HttpClient durchgeführt, was in der Program-Datei des Serverprojekts (BlazorApp) registriert ist:

builder.Services.AddHttpClient();

Rufen Sie eine interne Filmlisten-API (in der Blazor-Web-App) auf, bei der sich die API im Serverprojekt der Blazor-Web-App befindet:

  • BlazorApp: A Blazor-Web-App, mit der eine Filmliste verwaltet wird:
    • Wenn Vorgänge in der Filmliste innerhalb der App auf dem Server ausgeführt werden, werden gewöhnliche API-Aufrufe verwendet.
    • Wenn API-Aufrufe von einem webbasierten Client ausgeführt werden, wird basierend auf minimalen APIs eine Web-API für Filmlistenvorgänge verwendet.
  • BlazorApp.Client: Das Clientprojekt der Blazor-Web-App, das interaktive WebAssembly- und Autokomponenten für die Benutzerverwaltung der Filmliste enthält

Bei CSR, das interaktive WebAssembly-Komponenten und Autokomponenten umfasst, bei denen CSR verwendet wird, werden Aufrufe der API mit einem vorkonfigurierten clientseitigem Dienst (ClientMovieService) durchgeführt. Dieser nutzt HttpClient (vorkonfiguriert), was in der Program-Datei des Clientprojekts (BlazorApp.Client) registriert ist. Da diese Aufrufe über ein öffentliches oder privates Web erfolgen, ist die Filmlisten-API eine Web-API.

Im folgenden Beispiel wird eine Filmliste vom Endpunkt /movies abgerufen:

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

Bei SSR, das vorab gerenderte und interaktive Serverkomponenten, vorab gerenderte WebAssembly-Komponenten und Autokomponenten umfasst, die vorab gerendert wurden oder SSR verwenden, werden Aufrufe direkt mit einem serverbasierten Dienst (ServerMovieService) durchgeführt. Die API basiert nicht auf einem Netzwerk, daher ist sie eine Standard-API für CRUD-Vorgänge für Filmlisten.

Im folgenden Beispiel wird eine Filmliste abgerufen:

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

BlazorWebAppCallWebApi_Weather

Eine Beispiel-App für Wetterdaten, die Streamingrendering für Wetterdaten verwendet

BlazorWebAssemblyCallWebApi

Ruft eine Web-API einer Aufgabenliste aus einer Blazor WebAssembly-App auf:

  • Backend: Eine Web-API-App basierend auf Minimal-APIs zum Verwalten einer Aufgabenliste.
  • BlazorTodo: Eine Blazor WebAssembly-App, die die Web-API mit HttpClient (vorkonfiguriert) für CRUD-Vorgänge bei Aufgabenlisten aufruft.

Serverseitige Szenarios für das Aufrufen externer Web-APIs

Serverbasierte Komponenten rufen externe Web-APIs über HttpClient-Instanzen auf, die in der Regel mithilfe von IHttpClientFactory erstellt werden. Einen Leitfaden für serverseitige Apps finden Sie unter Stellen von HTTP-Anforderungen mithilfe von IHttpClientFactory in ASP.NET Core.

Eine serverseitige App enthält standardmäßig keinen HttpClient-Dienst. Stellen Sie der App über die HttpClient-Factory-Infrastruktur einen HttpClient zur Verfügung.

In der Program-Datei:

builder.Services.AddHttpClient();

Die folgende Razor-Komponente sendet eine Anforderung an eine Web-API für GitHub-Branches wie im Beispiel Grundlegende Verwendung im Artikel Stellen von HTTP-Anforderungen mithilfe von 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; }
    }
}

Im vorherigen Beispiel für C# 12 oder höher wird ein leeres Array ([]) für die Variable branches erstellt. Erstellen Sie für frühere C#-Versionen ein leeres Array (Array.Empty<GitHubBranch>()).

Ein weiteres funktionierendes Beispiel finden Sie im Beispiel zum serverseitigen Dateiupload zum Hochladen von Dateien in einen Web-API-Controller im Artikel Blazor-Dateiuploads in ASP.NET Core.

Dienstabstraktionen für Web-API-Aufrufe

Dieser Abschnitt gilt für Blazor-Web-Apps, die eine Web-API im Serverprojekt der App verwalten oder Web-API-Aufrufe an eine externe Web-API transformieren.

Wenn Sie die interaktiven WebAssembly- und Autorendermodi verwenden, werden Komponenten standardmäßig vorab gerendert. Autokomponenten werden zunächst auch interaktiv vom Server gerendert, bevor das Blazor-Bundle auf den Client heruntergeladen und die clientseitige Runtime aktiviert wird. Dies bedeutet, dass Komponenten, die diese Rendermodi verwenden, so konzipiert werden sollten, dass sie sowohl vom Client als auch vom Server erfolgreich ausgeführt werden können. Wenn die Komponente eine serverprojektbasierte API aufrufen oder eine Anforderung an eine externe Web-API (eine Web-API außerhalb der Blazor-Web-App) transformieren muss, während sie auf dem Client ausgeführt wird, empfiehlt es sich, diesen API-Aufruf hinter einer Dienstschnittstelle zu abstrahieren und Client- und Serverversionen des Diensts zu implementieren:

  • Die Clientversion ruft die Web-API mit HttpClient (vorkonfiguriert) auf.
  • Die Serverversion kann in der Regel direkt auf die serverseitigen Ressourcen zugreifen. Das Einfügen von HttpClient auf dem Server, der Aufrufe an den Server sendet, wird nicht empfohlen, da die Netzwerkanforderung in der Regel nicht erforderlich ist. Alternativ kann die API auch außerhalb des Serverprojekts liegen, aber eine Dienstabstraktion für den Server ist erforderlich, um die Anforderung in irgendeiner Weise umzuwandeln, z. B. um einer Proxy-Anfrage ein Zugriffstoken hinzuzufügen.

Wenn Sie den WebAssembly-Rendermodus verwenden, können Sie auch das Prerendering deaktivieren, sodass die Komponenten nur vom Client gerendert werden. Weitere Informationen finden Sie unter ASP.NET Core Blazor-Rendermodi.

Beispiele (Beispiel-Apps):

  • Web-API für eine Filmliste in der Beispiel-App BlazorWebAppCallWebApi
  • Streamingrendering der Wetterdaten-Web-API in der Beispiel-App BlazorWebAppCallWebApi_Weather
  • Wetterdaten, die in den Muster-Apps BlazorWebAppOidc (Nicht-BFF-Muster) oder BlazorWebAppOidcBff (BFF-Muster) an den Client zurückgegeben werden. Diese Anwendungen demonstrieren sichere (Web-)API-Aufrufe. Weitere Informationen finden Sie unter Sichern einer ASP.NET Core Blazor-Web App mit OpenID Connect (OIDC).

Externe Web-APIs der Web-App Blazor

Dieser Abschnitt gilt für Blazor-Web-Apps, die eine Web-API aufrufen, die von einem separaten (externen) Projekt verwaltet wird, das eventuell auf einem anderen Server gehostet wird.

Blazor Web Apps werden normalerweise clientseitige WebAssembly-Komponenten und Autokomponenten während des statischen oder interaktiven serverseitigen Renderings (SSR) auf dem Server gerendert. HttpClient-Dienste werden nicht standardmäßig im Hauptprojekt einer Blazor-Web-App registriert. Wenn die App nur mit den im .Client-Projekt registrierten HttpClient-Diensten ausgeführt wird, wie im Abschnitt Hinzufügen des HttpClient-Diensts beschrieben, führt die Ausführung der App zu einem Laufzeitfehler:

InvalidOperationException: Es kann kein Wert für die Eigenschaft 'Http' vom Typ '... {COMPONENT}'. Es gibt keinen registrierten Dienst vom Typ „System.Net.Http.HttpClient“.

Verwenden Sie einen der folgenden Ansätze:

  • Fügen Sie die HttpClient-Dienste zum Serverprojekt hinzu, um HttpClient während des SSR verfügbar zu machen. Verwenden Sie die folgende Dienstregistrierung in der Datei Program des Serverprojekts:

    builder.Services.AddHttpClient();
    

    Ein expliziter Paketverweis ist nicht erforderlich, da HttpClient-Dienste vom freigegebenen Framework bereitgestellt werden.

    Beispiel: Web-API für eine Aufgabenliste in der BlazorWebAppCallWebApiBeispiel-App

  • Wenn für eine WebAssembly-Komponente, die die Web-API aufruft, kein Prerendering erforderlich ist, deaktivieren Sie es, indem Sie dem Leitfaden im Artikel ASP.NET Core Blazor Rendermodi folgen. Wenn Sie diesen Ansatz verwenden, müssen Sie dem Hauptprojekt der Blazor-Web-App keine HttpClient-Dienste hinzufügen, da die Komponente nicht vorab auf dem Server gerendert wird.

Weitere Informationen finden Sie unter Clientseitige Dienste können während des Prerendering nicht aufgelöst werden..

Vorab gerenderte Daten

Beim Prerendering werden Komponenten zweimal gerendert: zuerst statisch, dann interaktiv. Der Zustand geht nicht automatisch von der vorab gerenderten Komponente in die interaktive über. Sollte eine Komponente asynchrone Initialisierungsvorgänge ausführen und während der Initialisierung unterschiedliche Inhalte für unterschiedliche Zustände rendern, z. B. eine Fortschrittsanzeige "Laden...", sehen Sie eventuell ein Flackern, wenn die Komponente zweimal gerendert wird.

Sie können dies beheben, indem Sie den vorab gerenderten Zustand mithilfe der API für den persistenten Komponentenstatus übergeben, was die BlazorWebAppCallWebApi und BlazorWebAppCallWebApi_WeatherBeispiel-Apps veranschaulichen. Wenn die Komponente interaktiv gerendert wird, kann sie mithilfe desselben Zustands auf die gleiche Weise gerendert werden. Die API funktioniert derzeit jedoch nicht mit erweiterter Navigation. Dies können Sie umgehen, indem Sie die erweiterte Navigation bei Links zur Seite deaktivieren (data-enhanced-nav=false). Weitere Informationen finden Sie in den folgenden Ressourcen:

Hinzufügen des HttpClient-Diensts

Die Anleitungen in diesem Abschnitt gelten für Client-seitige Szenarien.

Clientseitige Komponenten rufen Web-APIs mithilfe eines vorkonfigurierten HttpClient-Diensts auf, der hauptsächlich dazu dient, Anforderungen an den Ursprungsserver zu richten. Im Entwicklercode können zusätzliche HttpClient-Dienstkonfigurationen für andere Web-APIs erstellt werden. Anforderungen werden mithilfe von Blazor-JSON-Hilfsprogrammen oder mit HttpRequestMessage erstellt. Anforderungen können eine Konfiguration für Fetch API-Optionen enthalten.

Die Konfigurationsbeispiele in diesem Abschnitt sind nur hilfreich, wenn eine Web-API für eine HttpClient-Instanz in der App aufgerufen wird. Wenn die App mehrere Web-APIs aufrufen muss, die jeweils eine eigene Basisadresse und -konfiguration aufweisen, können Sie die folgenden Ansätze anwenden, die weiter unten in diesem Artikel behandelt werden:

Fügen Sie in der Datei Program einen HttpClient-Dienst hinzu, wenn er noch nicht aus einer Blazor-Projektvorlage vorhanden ist, die zum Erstellen der App verwendet wurde:

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

Im vorherigen Beispiel wird die Basisadresse mit builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress) festgelegt, wodurch die Basisadresse für die App abgerufen und in der Regel vom href-Wert des <base>-Tags auf der Hostseite abgeleitet wird.

Die häufigsten Anwendungsfälle für die Verwendung der Basisadresse des Clients sind:

  • Das Clientprojekt (.Client) einer Blazor-Web-App (.NET 8 oder höher) führt Web-API-Aufrufe an APIs in der Server-App über WebAssembly-Komponenten oder Code aus, der auf dem Client in WebAssembly ausgeführt wird.
  • Das Clientprojekt (Client) einer gehosteten Blazor WebAssembly-App tätigt Web-API-Aufrufe an das Serverprojekt (Server). Beachten Sie, dass die gehostete Blazor WebAssembly-Projektvorlage in .NET 8 oder höher nicht mehr verfügbar ist. Gehostete Blazor WebAssembly-Apps werden jedoch für .NET 8 weiterhin unterstützt.

Wenn Sie eine externe Web-API aufrufen (nicht im gleichen URL-Bereich wie die Client-App), legen Sie den URI auf die Basisadresse der Web-API fest. Im folgenden Beispiel wird die Basisadresse der Web-API auf https://localhost:5001 festgelegt, wobei eine separate Web-API-App ausgeführt wird und bereit ist, auf Anforderungen von der Client-App zu reagieren:

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

JSON-Hilfsprogramme

HttpClient ist als vorkonfigurierter Dienst zum Senden von Anforderungen zurück an den Ursprungsserver verfügbar.

HttpClient- und JSON-Hilfsprogramme (System.Net.Http.Json.HttpClientJsonExtensions) werden auch zum Aufrufen von Web-API-Endpunkten von Drittanbietern verwendet. HttpClient wird mithilfe der Fetch-API des Browsers implementiert und unterliegt dessen Beschränkungen, einschließlich der Erzwingung der Richtlinie für denselben Ursprung, die weiter unten in diesem Artikel im Abschnitt Cross-Origin Resource Sharing (CORS) besprochen wird.

Die Basisadresse des Clients wird auf die Adresse des Ursprungsservers festgelegt. Fügen Sie mit der @inject-Direktive eine HttpClient-Instanz in eine Komponente ein:

@using System.Net.Http
@inject HttpClient Http

Verwenden Sie den System.Net.Http.Json-Namespace für den Zugriff auf HttpClientJsonExtensions, einschließlich GetFromJsonAsync, PutAsJsonAsync und PostAsJsonAsync:

@using System.Net.Http.Json

In den folgenden Abschnitten werden JSON-Hilfsprogramme behandelt:

System.Net.Http enthält zusätzliche Methoden zum Senden von HTTP-Anforderungen und Empfangen von HTTP-Antworten, zum Beispiel zum Senden einer DELETE-Anforderung. Weitere Informationen finden Sie im Abschnitt DELETE und zusätzliche Erweiterungsmethoden.

GET von JSON (GetFromJsonAsync)

GetFromJsonAsync sendet eine HTTP-GET-Anforderung und analysiert den JSON-Antworttext, um ein Objekt zu erstellen.

Im folgenden Komponentencode werden die todoItems von der Komponente angezeigt. GetFromJsonAsync wird aufgerufen, wenn die Initialisierung (OnInitializedAsync) der Komponente beendet wurde.

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

POST als JSON (PostAsJsonAsync)

PostAsJsonAsync sendet eine POST-Anforderung an den angegebenen URI, wobei der als JSON-Code serialisierte Wert im Anforderungstext enthalten ist.

Im folgenden Komponentencode wird newItemName durch ein gebundenes Element der Komponente bereitgestellt. Die AddItem-Methode wird durch Auswählen eines <button>-Elements ausgelöst.

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

HttpResponseMessage gibt PostAsJsonAsync zurück. Um den JSON-Inhalt aus der Antwortnachricht zu deserialisieren, verwenden Sie die ReadFromJsonAsync-Erweiterungsmethode. Im folgenden Beispiel werden JSON-Wetterdaten als Array gelesen:

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

PUT als JSON (PutAsJsonAsync)

PutAsJsonAsync sendet eine HTTP-PUT-Anforderung mit JSON-codiertem Inhalt.

Im folgenden Komponentencode werden editItem-Werte für Name und IsCompleted durch gebundene Elemente der Komponente bereitgestellt. Die Id des Elements wird festgelegt, wenn das Element in einem anderen Teil der Benutzeroberfläche (nicht gezeigt) ausgewählt und EditItem aufgerufen wird. Die SaveItem-Methode wird durch Auswahl des <button>-Elements ausgelöst. Im folgenden Beispiel wird das Laden von todoItems aus Gründen der Übersichtlichkeit nicht angezeigt. Im Abschnitt GET von JSON (GetFromJsonAsync) finden Sie ein Beispiel für das Laden von Elementen.

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

HttpResponseMessage gibt PutAsJsonAsync zurück. Um den JSON-Inhalt aus der Antwortnachricht zu deserialisieren, verwenden Sie die ReadFromJsonAsync-Erweiterungsmethode. Im folgenden Beispiel werden JSON-Wetterdaten als Array gelesen:

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

PATCH als JSON (PatchAsJsonAsync)

PatchAsJsonAsync sendet eine HTTP-PATCH-Anforderung mit JSON-codiertem Inhalt.

Hinweis

Weitere Informationen finden Sie unter JsonPatch in ASP.NET Core-Web-APIs.

Im folgenden Beispiel empfängt PatchAsJsonAsync ein JSON PATCH-Dokument als Nur-Text-Zeichenfolge mit Escapezeichen:

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

HttpResponseMessage gibt PatchAsJsonAsync zurück. Um den JSON-Inhalt aus der Antwortnachricht zu deserialisieren, verwenden Sie die ReadFromJsonAsync-Erweiterungsmethode. Im folgenden Beispiel werden JSON-Daten von Aufgabenlistenelementen als Array gelesen. Ein leeres Array wird erstellt, wenn keine Elementdaten von der Methode zurückgegeben werden. content ist also nach Ausführen der Anweisung nicht NULL:

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

Das nicht codierte PATCH-Dokument mit Einzug, Abstand und Anführungszeichen ohne Escapezeichen wird als das folgende JSON angezeigt:

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

Um die Erstellung von PATCH-Dokumenten in der App zu vereinfachen, die PATCH-Anforderungen ausstellen, kann eine App die .NET JSON PATCH-Unterstützung verwenden, wie die folgende Anleitung veranschaulicht.

Installieren Sie das NuGet-Paket „Microsoft.AspNetCore.JsonPatch“, und verwenden Sie die API-Features des Pakets, um eine JsonPatchDocument für eine PATCH-Anforderung zu erstellen.

Hinweis

Einen Leitfaden zum Hinzufügen von Paketen zu .NET-Apps finden Sie in Installieren und Verwalten von Paketen unter Workflow der Nutzung von Paketen (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Fügen Sie eine @using-Anweisung für den Namespace System.Text.Json, System.Text.Json.Serialization, und Microsoft.AspNetCore.JsonPatch oben in der Razor-Komponente hinzu:

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

Erstellen Sie die JsonPatchDocument für eine TodoItem mit IsComplete festgelegt auf true, indem Sie die Replace-Methode verwenden:

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

Übergeben Sie die Vorgänge des Dokuments (patchDocument.Operations) an den Aufruf PatchAsJsonAsync:

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

JsonSerializerOptions.DefaultIgnoreCondition wird auf JsonIgnoreCondition.WhenWritingDefault festgelegt, um eine Eigenschaft nur zu ignorieren, wenn sie dem Standardwert für ihren Typ entspricht.

Fügen Sie JsonSerializerOptions.WriteIndented hinzu, das auf true festgelegt ist, um die JSON-Nutzlast in einem angenehmen Format darzustellen. Das Schreiben von eingezogenen JSON hat keinen Einfluss auf die Verarbeitung von PATCH-Anforderungen und wird in der Regel nicht in Produktions-Apps für Web-API-Anforderungen ausgeführt.

Befolgen Sie die Anleitung im Artikel JsonPatch in ASP.NET Core Web-API, um der Web-API eine PATCH-Controlleraktion hinzuzufügen. Alternativ kann die PATCH-Anforderungsverarbeitung mit den folgenden Schritten als Minimal-API implementiert werden.

Fügen Sie der Web-API-App einen Paketverweis für das NuGet-Paket „Microsoft.AspNetCore.Mvc.NewtonsoftJson“ hinzu.

Hinweis

Es ist nicht erforderlich, der App einen Paketverweis für das Microsoft.AspNetCore.JsonPatch-Paket hinzuzufügen, da der Verweis auf das Microsoft.AspNetCore.Mvc.NewtonsoftJson-Paket automatisch transitiv einen Paketverweis für Microsoft.AspNetCore.JsonPatch hinzufügt.

Fügen Sie in der Datei Program eine @using-Anweisung für den Namespace Microsoft.AspNetCore.JsonPatch hinzu:

using Microsoft.AspNetCore.JsonPatch;

Stellen Sie den Endpunkt für die Anforderungsverarbeitungspipeline der Web-API bereit:

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

Warnung

Wie bei den anderen Beispielen im Artikel JsonPatch in ASP.NET Core Web-API schützt die vorangehende PATCH-API die Web-API nicht vor Overpostingangriffen. Weitere Informationen finden Sie unter Tutorial: Erstellen einer Web-API-App mit ASP.NET Core.

Eine voll funktionsfähige PATCH-Anwendung finden Sie in der BlazorWebAppCallWebApiBeispielapp.

DELETE (DeleteAsync) und weitere Erweiterungsmethoden

System.Net.Http enthält zusätzliche Erweiterungsmethoden zum Senden von HTTP-Anforderungen und Empfangen von HTTP-Antworten. HttpClient.DeleteAsync wird verwendet, um eine HTTP-DELETE-Anforderung an eine Web-API zu senden.

Im folgenden Komponentencode ruft das <button>-Element die DeleteItem-Methode auf. Das gebundene <input>-Element stellt die id des zu löschenden Elements bereit.

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

Benennung von HttpClient mit IHttpClientFactory

IHttpClientFactory-Dienste und die Konfiguration einer benannten HttpClient werden unterstützt.

Hinweis

Eine Alternative zur Verwendung eines benannten HttpClient aus einer IHttpClientFactory ist die Verwendung eines typisierten HttpClient. Weitere Informationen finden Sie im Abschnitt Typisierter HttpClient.

Fügen Sie der App das NuGet-Paket Microsoft.Extensions.Http hinzu.

Hinweis

Einen Leitfaden zum Hinzufügen von Paketen zu .NET-Apps finden Sie in Installieren und Verwalten von Paketen unter Workflow der Nutzung von Paketen (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

In der Datei Program eines Clientprojekts:

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

Wenn der benannte Client von vorab gerenderten clientseitigen Komponenten einer Blazor-Web-App verwendet werden soll, sollte die vorangehende Dienstregistrierung sowohl im Serverprojekt als auch im Projekt .Client erscheinen. Auf dem Server wird builder.HostEnvironment.BaseAddress durch die Basisadresse der Web-API ersetzt, die weiter unten beschrieben wird.

Im vorherigen clientseitigen Beispiel wird die Basisadresse mit builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress) festgelegt, wodurch die Basisadresse für die clientseitige App abgerufen und in der Regel vom href-Wert des <base>-Tags auf der Hostseite abgeleitet wird.

Die häufigsten Anwendungsfälle für die Verwendung der Basisadresse des Clients sind:

  • Das Clientprojekt (.Client) einer Blazor-Web-App, das Web-API-Aufrufe von WebAssembly/Auto-Komponenten oder Code, der auf dem Client in WebAssembly ausgeführt wird, an APIs in der Serveranwendung unter derselben Hostadresse vornimmt.
  • Das Clientprojekt (Client) einer gehosteten Blazor WebAssembly-App, das Web-API-Aufrufe an das Serverprojekt (Server) vornimmt.

Der häufigste Anwendungsfall für die Verwendung der eigenen Basisadresse des Clients ist das Client-Projekt (Client) einer gehosteten Blazor WebAssembly-App, die Web-API-Aufrufe an das Server-Projekt (Server) richtet.

Wenn Sie eine externe Web-API aufrufen (die sich nicht im selben URL-Bereich wie die Client-Anwendung befindet) oder wenn Sie die Dienste in einer serverseitigen Anwendung konfigurieren (z.B. um das Prerendering von clientseitigen Komponenten auf dem Server zu ermöglichen), legen Sie die URI auf die Basisadresse der Web-API fest. Im folgenden Beispiel wird die Basisadresse der Web-API auf https://localhost:5001 festgelegt, wobei eine separate Web-API-App ausgeführt wird und bereit ist, auf Anforderungen von der Client-App zu reagieren:

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

Im folgenden Komponentencode:

  • Erstellt eine Instanz von IHttpClientFactory einen benannten HttpClient.
  • Der benannte HttpClient wird verwendet, um eine GET-Anforderung für JSON-Wettervorhersagedaten von der Web-API auf /forecast zu stellen.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

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

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

Die BlazorWebAppCallWebApiBeispiel-App veranschaulicht das Aufrufen einer Web-API mit einem benannten HttpClient in der Komponente CallTodoWebApiCsrNamedClient. Ein weiteres funktionierendes Beispiel in einer Client-Anwendung, die auf dem Aufruf von Microsoft Graph mit einer benannten HttpClient-Instanz basiert, finden Sie unter Verwenden der Graph-API mit ASP.NET Core Blazor WebAssembly.

Ein funktionierendes Beispiel für eine Client-Anwendung, die auf dem Aufruf von Microsoft Graph mit einem benannten HttpClient-Instanz basiert, finden Sie unter Verwenden der Graph-API mit ASP.NET Core Blazor WebAssembly.

Typisierter HttpClient

Eine typisierte HttpClient verwendet mindestens eine HttpClient-Instanz der App (Standardinstanz oder benannte Instanz), um Daten aus einem oder mehreren Web-API-Endpunkten zurückzugeben.

Hinweis

Eine Alternative zur Verwendung eines typisierten HttpClient ist die Verwendung eines benannten HttpClient aus einer IHttpClientFactory. Weitere Informationen finden Sie im Abschnitt Benannter HttpClient mit IHttpClientFactory.

Fügen Sie der App das NuGet-Paket Microsoft.Extensions.Http hinzu.

Hinweis

Einen Leitfaden zum Hinzufügen von Paketen zu .NET-Apps finden Sie in Installieren und Verwalten von Paketen unter Workflow der Nutzung von Paketen (NuGet-Dokumentation). Überprüfen Sie unter NuGet.org, ob die richtige Paketversion verwendet wird.

Das folgende Beispiel stellt eine GET-Anforderung für JSON-Wettervorhersagedaten von der Web-API auf /forecast.

ForecastHttpClient.cs:

using System.Net.Http.Json;

namespace BlazorSample.Client;

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

In der Datei Program eines Clientprojekts:

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

Wenn der Clienttyp von vorab gerenderten clientseitigen Komponenten einer Blazor-Web-App verwendet werden soll, sollte die vorangehende Dienstregistrierung sowohl im Serverprojekt als auch im Projekt .Client erscheinen. Auf dem Server wird builder.HostEnvironment.BaseAddress durch die Basisadresse der Web-API ersetzt, die weiter unten beschrieben wird.

Im vorherigen Beispiel wird die Basisadresse mit builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress) festgelegt, wodurch die Basisadresse für die clientseitige App abgerufen und in der Regel vom href-Wert des <base>-Tags auf der Hostseite abgeleitet wird.

Die häufigsten Anwendungsfälle für die Verwendung der Basisadresse des Clients sind:

  • Das Clientprojekt (.Client) einer Blazor-Web-App, das Web-API-Aufrufe von WebAssembly/Auto-Komponenten oder Code, der auf dem Client in WebAssembly ausgeführt wird, an APIs in der Serveranwendung unter derselben Hostadresse vornimmt.
  • Das Clientprojekt (Client) einer gehosteten Blazor WebAssembly-App, das Web-API-Aufrufe an das Serverprojekt (Server) vornimmt.

Der häufigste Anwendungsfall für die Verwendung der eigenen Basisadresse des Clients ist das Client-Projekt (Client) einer gehosteten Blazor WebAssembly-App, die Web-API-Aufrufe an das Server-Projekt (Server) richtet.

Wenn Sie eine externe Web-API aufrufen (die sich nicht im selben URL-Bereich wie die Client-Anwendung befindet) oder wenn Sie die Dienste in einer serverseitigen Anwendung konfigurieren (z.B. um das Prerendering von clientseitigen Komponenten auf dem Server zu ermöglichen), legen Sie die URI auf die Basisadresse der Web-API fest. Im folgenden Beispiel wird die Basisadresse der Web-API auf https://localhost:5001 festgelegt, wobei eine separate Web-API-App ausgeführt wird und bereit ist, auf Anforderungen von der Client-App zu reagieren:

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

Komponenten fügen die typisierte HttpClient-Instanz zum Aufruf der Web-API ein.

Im folgenden Komponentencode:

  • Wird eine Instanz von ForecastHttpClient eingefügt, wodurch ein typisierter HttpClient erstellt wird.
  • Der typisierte HttpClient wird verwendet, um eine GET-Anforderung für JSON-Wettervorhersagedaten von der Web-API auszugeben.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

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

Die BlazorWebAppCallWebApiBeispiel-App veranschaulicht das Aufrufen einer Web-API mit einem HttpClient-Typ in der Komponente CallTodoWebApiCsrTypedClient. Beachten Sie, dass die Komponente das clientseitige Rendering (CSR) (Rendering-Modus InteractiveWebAssembly) mit Prerendering verwendet, so dass die eingegebene Registrierung des Client-Dienstes sowohl in der Datei Program des Server-Projekts als auch im Projekt .Client erscheint.

Die Anleitung in diesem Abschnitt gilt für clientseitige Szenarien, die auf der cookie-Authentifizierung basieren.

Bei der auf cookie basierten Authentifizierung, die als sicherer gilt als die Bearertokenauthentifizierung, können cookie-Anmeldeinformationen mit jeder Web-API-Anforderung gesendet werden, indem AddHttpMessageHandler mit einer für DelegatingHandler vorkonfigurierten HttpClient aufgerufen wird. Der Handler konfiguriert SetBrowserRequestCredentials mit BrowserRequestCredentials.Include, was dem Browser empfiehlt, Anmeldeinformationen mit jeder Anforderung zu senden, z. B. cookie- oder HTTP-Authentifizierungsheader, einschließlich für ursprungsübergreifende Anforderungen.

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

Die CookieHandler ist in der Program-Datei registriert:

builder.Services.AddScoped<CookieHandler>();

Der Nachrichtenhandler wird allen vorkonfigurierten HttpClient, die eine Authentifizierung erfordern cookie, hinzugefügt:

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

Wenn Sie eine HttpRequestMessage erstellen, legen Sie die Anmeldeinformationen und den Header des Browsers direkt fest:

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

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

HttpClient und HttpRequestMessage mit Abruf-API-Anforderungsoptionen

Die Anleitung in diesem Abschnitt gilt für clientseitige Szenarien, die auf der Bearertoken-Authentifizierung basieren.

Zum Anpassen von Anforderungen können HttpClient (API-Dokumentation) und HttpRequestMessage verwendet werden. Beispielsweise können Sie die HTTP-Methode und die Anforderungsheader angeben. Die folgende Komponente sendet eine POST-Anforderung an einen API-Endpunkt auf dem Server und zeigt den Antworttext an.

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

Die clientseitige Blazor-Implementierung von HttpClient verwendet die Fetch-API und konfiguriert die zugrunde liegenden anforderungsspezifischen Fetch-API-Optionen über HttpRequestMessage-Erweiterungsmethoden und WebAssemblyHttpRequestMessageExtensions. Legen Sie mithilfe der allgemeinen SetBrowserRequestOption-Erweiterungsmethode weitere Optionen fest. Blazor und die zugrunde liegende Fetch-API fügen keine Anforderungsheader direkt hinzu oder ändern sie. Weitere Informationen dazu, wie Benutzer-Agents, z. B. Browser, mit Headern interagieren, finden Sie in den Dokumentationen für externe Benutzer-Agents und anderen Webressourcen.

Die HTTP-Antwort wird in der Regel gepuffert, um eine Unterstützung von synchronen Lesevorgängen im Antwortinhalt zu ermöglichen. Um Unterstützung für Streaming von Antworten zu aktivieren, verwenden Sie die SetBrowserResponseStreamingEnabled-Erweiterungsmethode für die Anforderung.

Wenn Sie Anmeldeinformationen in eine ursprungsübergreifende Anforderung einschließen möchten, verwenden Sie die SetBrowserRequestCredentials-Erweiterungsmethode:

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Weitere Informationen zu Fetch API-Optionen finden Sie unter MDN Web Docs: WindowOrWorkerGlobalScope.fetch(): Parameter.

Behandeln von Fehlern

Behandeln Sie auftretende Web-API-Antwortfehler im Entwicklercode. Beispielsweise erwartet GetFromJsonAsync eine JSON-Antwort mit einem Content-Type von application/json von der Web-API. Wenn die Antwort nicht im JSON-Format vorliegt, löst die Inhaltsüberprüfung eine NotSupportedException aus.

Im folgenden Beispiel ist der URI-Endpunkt für die Anforderung der Wettervorhersagedaten falsch geschrieben. Der URI muss WeatherForecast sein, wird aber im Aufruf als WeatherForcast angezeigt, sodass der Buchstabe e in Forecast fehlt.

Der GetFromJsonAsync-Aufruf erwartet, dass JSON zurückgegeben wird, die Web-API gibt jedoch HTML für einen Ausnahmefehler mit einem Content-Type von text/html zurück. Der Ausnahmefehler tritt auf, da der Pfad zu /WeatherForcast nicht gefunden wurde und die Middleware keine Seite oder Ansicht für die Anforderung bereitstellen kann.

In OnInitializedAsync auf dem Client wird NotSupportedException ausgelöst, wenn der Inhalt der Antwort als Nicht-JSON-Code überprüft wird. Die Ausnahme wird im catch-Block abgefangen, in dem die benutzerdefinierte Logik den Fehler protokollieren oder eine benutzerfreundliche Fehlermeldung an den Benutzer senden kann.

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

Hinweis

Das vorherige Beispiel dient nur der Veranschaulichung. Eine Web-API kann so konfiguriert werden, dass JSON auch dann zurückgegeben wird, wenn kein Endpunkt vorhanden ist oder auf dem Server ein Ausnahmefehler auftritt.

Weitere Informationen finden Sie unter Fehlerbehandlung in Blazor-Apps in in ASP.NET Core.

Ressourcenfreigabe zwischen verschiedenen Ursprüngen (Cross-Origin Resource Sharing, CORS)

Die Browsersicherheit schränkt das Senden von Anforderungen von der Webseite an eine andere Domäne als diejenige ein, die die Webseite bereitgestellt hat. Diese Einschränkung wird als Richtlinie des gleichen Ursprungs bezeichnet. Die Richtlinie des gleichen Ursprungs schränkt ebenfalls ein, dass eine schädliche Website sensible Daten von einer anderen Website liest, verhindert dies aber nicht. Um Anforderungen vom Browser an einen Endpunkt mit einem anderen Ursprung zu stellen, muss der Endpunkt die Ressourcenfreigabe zwischen verschiedenen Ursprüngen (Cross-Origin Resource Sharing, CORS) ermöglichen.

Weitere Informationen zu serverseitigem CORS finden Sie unter Cross-Origin Requests (CORS) in ASP.NET Core aktivieren. Die Beispiele des Artikels beziehen sich nicht direkt auf Razor-Komponentenszenarien. Der Artikel ist dennoch hilfreich, um allgemeine CORS-Konzepte kennenzulernen.

Informationen zu clientseitigen CORS-Anforderungen finden Sie unter Zusätzliche Sicherheitsszenarien für Blazor WebAssembly in ASP.NET Core.

Unterstützung des Schutzes vor Fälschung

Um einer HTTP-Anforderung mit Unterstützung für die Fälschungssicherheit zu versehen, injizieren Sie AntiforgeryStateProvider und fügen Sie der Header-Sammlung RequestToken als RequestVerificationToken hinzu:

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

Weitere Informationen hierzu finden Sie unter Authentifizierung und Autorisierung in ASP.NET Core Blazor.

Beispiele für Blazor-Frameworkkomponenten zum Testen des Web-API-Zugriffs

Zum direkten Testen von Back-End-Apps mit Web-APIs sind verschiedene Netzwerktools öffentlich verfügbar, z. B. Firefox Browser Developer. Die Referenzquelle des Blazor-Frameworks enthält HttpClient-Testressourcen, die für Tests nützlich sind:

HttpClientTest-Ressourcen im dotnet/aspnetcore GitHub-Repository

Hinweis

Dokumentationslinks zur .NET-Referenzquelle laden in der Regel den Standardbranch des Repositorys, der die aktuelle Entwicklung für das nächste Release von .NET darstellt. Um ein Tag für ein bestimmtes Release auszuwählen, wählen Sie diesen mit der Dropdownliste Switch branches or tags (Branches oder Tags wechseln) aus. Weitere Informationen finden Sie unter How to select a version tag of ASP.NET Core source code (dotnet/AspNetCore.Docs #26205) (Auswählen eines Versionstags von ASP.NET Core-Quellcode (dotnet/AspNetCore.Docs #26205)).

Zusätzliche Ressourcen

Allgemein

Serverseitig

Clientseitig