Dela via


Anropa ett webb-API från ASP.NET Core Blazor

Not

Det här är inte den senaste versionen av den här artikeln. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Varning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i .NET och .NET Core Support Policy. Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

Viktig

Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.

Den aktuella versionen finns i den .NET 9-versionen av den här artikeln.

I den här artikeln beskrivs hur du anropar ett webb-API från en Blazor app.

Paket

System.Net.Http.Json-paketet innehåller tilläggsmetoder för System.Net.Http.HttpClient och System.Net.Http.HttpContent som utför automatisk serialisering och deserialisering med hjälp av System.Text.Json. Det System.Net.Http.Json paketet tillhandahålls av det delade .NET-ramverket och kräver inte att du lägger till en paketreferens till appen.

Exempelappar

Se exempelapparna på dotnet/blazor-samples GitHub-lagringsplats.

BlazorWebAppCallWebApi

Anropa ett externt att-göra-lista webb-API (inte i Blazor Web App) från en Blazor Web App:

  • Backend: En webb-API-app för att hålla en att göra-lista uppdaterad, baserat på Minimal APIs. Webb-API-appen är en separat app från Blazor Web App, som eventuellt finns på en annan server.
  • BlazorApp / BlazorApp.Client: En Blazor Web App som anropar webb-API-appen med en HttpClient för åtgärder i att göra-listan, såsom att skapa, läsa, uppdatera och ta bort (CRUD)-objekt från att göra-listan.

För återgivning på klientsidan (CSR), som innehåller interaktiva WebAssembly-komponenter och automatiska komponenter som har antagit CSR, görs anrop med en förkonfigurerad HttpClient registrerad i Program-filen i klientprojektet (BlazorApp.Client):

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

För återgivning på serversidan (SSR), som innehåller interaktiva och förrenderade serverkomponenter, förrenderade WebAssembly-komponenter och automatiska komponenter som är förrenderade eller har använt SSR, görs anrop med en HttpClient registrerad i Program-filen i serverprojektet (BlazorApp):

builder.Services.AddHttpClient();

Anropa en intern filmliste-API inne i Blazor Web App, där API:et finns i serverprojektet för Blazor Web App.

  • BlazorApp: En Blazor Web App som har en filmlista:
    • När åtgärder utförs i filmlistan i appen på servern används vanliga API-anrop.
    • När API-anrop görs av en webbaserad klient används ett webb-API för hantering av filmlistor baserat på Minimal-API:er.
  • BlazorApp.Client: Klientprojektet för Blazor Web App, som innehåller interaktiva WebAssembly- och Auto-komponenter för användarhantering av filmlistan.

För CSR, som innehåller interaktiva WebAssembly-komponenter och automatiska komponenter som har antagit CSR, görs anrop till API:et via en klientbaserad tjänst (ClientMovieService) som använder en förkonfigurerad HttpClient registrerad i Program-filen i klientprojektet (BlazorApp.Client). Eftersom dessa anrop görs via en offentlig eller privat webb är API:et för filmlistan ett webb-API.

I följande exempel hämtas en lista över filmer från /movies slutpunkten:

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

För SSR, som innehåller förinstallerade och interaktiva serverkomponenter, förrenderade WebAssembly-komponenter och automatiska komponenter som är förinstallerade eller har antagit SSR, görs anrop direkt via en serverbaserad tjänst (ServerMovieService). API:et förlitar sig inte på ett nätverk, så det är ett standard-API för CRUD-åtgärder i filmlistan.

I följande exempel hämtas en lista över filmer:

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

En exempelapp för väderdata som använder strömmande rendering för väderdata.

BlazorWebAssemblyCallWebApi

Anropar ett webb-API för att-göra-lista från en Blazor WebAssembly-app:

  • Backend: En webb-API-applikation för att hantera en att göra-lista baserad på Minimal APIs.
  • BlazorTodo: En Blazor WebAssembly-app som anropar webb-API:et med en förkonfigurerad HttpClient för CRUD-operationer på en att-göra-lista.

Scenarier på klientsidan för att anropa externa webb-API:er

Klientbaserade komponenter anropar externa webb-API:er med hjälp av HttpClient-instanser, som vanligtvis skapas med en förkonfigurerad HttpClient registrerad i filen Program:

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

Följande Razor-komponent skickar en begäran till ett webb-API för GitHub-grenar liknande exemplet Grundläggande användning i artikeln Göra HTTP-förfrågningar med IHttpClientFactory i ASP.NET Core.

CallWebAPI.razor:

@page "/call-web-api"
@using System.Text.Json
@using System.Text.Json.Serialization
@inject HttpClient Client

<h1>Call web API from a Blazor WebAssembly 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 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; }
    }
}

I föregående exempel för C# 12 eller senare skapas en tom matris ([]) för variabeln branches. För tidigare versioner av C# som kompilerats med ett SDK tidigare än .NET 8 skapar du en tom matris (Array.Empty<GitHubBranch>()).

Om du vill skydda .NET/C#-kod och data använder du ASP.NET Core Data Protection- funktioner med ett serverbaserat ASP.NET Core backend webb-API. Klientsidans Blazor WebAssembly app anropar webb-API:et på serversidan för säkra appfunktioner och databearbetning.

Blazor WebAssembly appar hindras ofta från att direkt anropa webb-API:er över olika ursprung på grund av CORS-säkerhet (CORS, delning av förfrågningar över olika ursprung). Ett typiskt undantag ser ut så här:

Åtkomst till att hämta på {URL} från ursprungethttps://localhost:{PORT}' har blockerats av CORS-principen: Inget "Access-Control-Allow-Origin"-huvud finns på den begärda resursen. Om ett ogenomskinligt svar uppfyller dina behov, ställ in begärans läge på 'no-cors' för att hämta resursen med CORS inaktiverat.

Även om du anropar SetBrowserRequestMode med ett BrowserRequestMode fält i NoCors (1) som försöker kringgå föregående undantag misslyckas begäran ofta på grund av CORS-begränsningar för webb-API:ets ursprung, till exempel en begränsning som endast tillåter anrop från specifika ursprung eller en begränsning som förhindrar JavaScript-fetch begäranden från en webbläsare. Det enda sättet för sådana anrop att lyckas är om webb-API:et som du anropar tillåter ditt ursprung att anropa dess ursprung med korrekt CORS-konfiguration. De flesta externa webb-API:er tillåter inte att du konfigurerar deras CORS-principer. Anta någon av följande strategier för att hantera den här begränsningen:

  • Underhåll ditt eget ASP.NET Core-backendwebb-API på serversidan. Klientsidans Blazor WebAssembly app anropar webb-API:et på serversidan och webb-API:et skickar begäran från sin serverbaserade C#-kod (inte en webbläsare) till det externa webb-API:et med rätt CORS-huvuden, vilket returnerar resultatet till din Blazor WebAssembly app på klientsidan.

  • Använd en proxytjänst för att skicka begäran från Blazor WebAssembly app på klientsidan till det externa webb-API:et. Proxytjänsten använder en app på serversidan för att göra begäran åt klienten och returnerar resultatet när anropet har slutförts. I följande exempel baserat på CloudFlares CORS PROXY, är {REQUEST URI} platshållaren för begäran-URI:n.

    @using System.Net
    @inject IHttpClientFactory ClientFactory
    
    ...
    
    @code {
        public async Task CallApi()
        {
            var client = ClientFactory.CreateClient();
    
            var urlEncodedRequestUri = WebUtility.UrlEncode("{REQUEST URI}");
    
            var request = new HttpRequestMessage(HttpMethod.Get, 
                $"https://corsproxy.io/?{urlEncodedRequestUri}");
    
            var response = await client.SendAsync(request);
    
            ...
        }
    }
    

Scenarier på serversidan för att anropa externa webb-API:er

Serverbaserade komponenter anropar externa webb-API:er med hjälp av HttpClient-instanser, som vanligtvis skapas med hjälp av IHttpClientFactory. Vägledning som gäller för appar på serversidan finns i Göra HTTP-begäranden med IHttpClientFactory i ASP.NET Core.

En app på serversidan innehåller inte någon HttpClient tjänst. Ange en HttpClient till appen genom att använda fabriksinfrastrukturen HttpClient.

I filen Program:

builder.Services.AddHttpClient();

Följande Razor-komponent gör en förfrågan till ett webb-API för GitHub-grenar som liknar exemplet Grundläggande användning i artikeln Göra HTTP-förfrågningar med IHttpClientFactory i 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 server-side 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; }
    }
}

I föregående exempel för C# 12 eller senare skapas en tom matris ([]) för variabeln branches. För tidigare versioner av C# som kompilerats med ett SDK tidigare än .NET 8 skapar du en tom matris (Array.Empty<GitHubBranch>()).

Ett ytterligare arbetsexempel finns i exemplet med filuppladdning på serversidan som laddar upp filer till en webb-API-kontrollant i artikeln ASP.NET Core Blazor filuppladdningar.

Tjänstabstraktioner för webb-API-anrop

Det här avsnittet gäller för Blazor Web Appsom underhåller ett webb-API i serverprojektet eller transformerar webb-API-anrop till ett externt webb-API.

När du använder de interaktiva WebAssembly- och Autoåtergivningslägena förbereds komponenterna som standardinställning. Automatiska komponenter återges också interaktivt från servern innan Blazor paket laddas ned till klienten och körningen på klientsidan aktiveras. Det innebär att komponenter som använder dessa återgivningslägen bör utformas så att de körs från både klienten och servern. Om komponenten måste anropa ett serverprojektbaserat API eller transformera en begäran till ett externt webb-API (ett som ligger utanför Blazor Web App) när den körs på klienten, är den rekommenderade metoden att abstrahera API-anropet bakom ett tjänstgränssnitt och implementera klient- och serverversioner av tjänsten:

  • Klientversionen anropar webb-API:et med en förkonfigurerad HttpClient.
  • Serverversionen kan vanligtvis komma åt resurserna på serversidan direkt. Att mata in en HttpClient på servern som gör anrop tillbaka till servern rekommenderas inte, eftersom nätverksbegäran vanligtvis är onödig. Alternativt kan API:et vara externt för serverprojektet, men en tjänstabstraktion för servern krävs för att transformera begäran på något sätt, till exempel för att lägga till en åtkomsttoken till en proxied-begäran.

När du använder webassembly-återgivningsläget har du också möjlighet att inaktivera förrendering, så att komponenterna bara återges från klienten. Mer information finns i ASP.NET Core Blazor återgivningslägen.

Exempel (exempelappar):

  • Webb-API för filmlista i BlazorWebAppCallWebApi exempelapp.
  • Webb-API för strömmande rendering av väderdata i BlazorWebAppCallWebApi_Weather exempelapp.
  • Väderdata returnerades till klienten i antingen BlazorWebAppOidc (icke-BFF-mönster) eller BlazorWebAppOidcBff (BFF-mönster) i prototypapparna. Dessa appar demonstrerar säkra API-anrop (webb). Mer information finns i Secure an ASP.NET Core Blazor Web App with OpenID Connect (OIDC).

Blazor Web App externa webb-APIer

Det här avsnittet gäller för Blazor Web Appsom anropar ett webb-API som underhålls av ett separat (externt) projekt, som eventuellt finns på en annan server.

Blazor Web Appvanligtvis förprerender WebAssembly-komponenter på klientsidan, och Auto-komponenter återges på servern under statisk eller interaktiv serverside-återgivning (SSR). HttpClient tjänster registreras inte som standard i ett Blazor Web Apphuvudprojekt. Om appen körs med endast de HttpClient tjänster som registrerats i .Client projektet, enligt beskrivningen i avsnittet Lägg till HttpClient-tjänsten, resulterar körningen av appen i ett körningsfel:

InvalidOperationException: Det går inte att ange ett värde för egenskapen Http på typen ... {KOMPONENT}'. Det finns ingen registrerad tjänst av typen "System.Net.Http.HttpClient".

Använd antingen av följande metoder:

  • Lägg till HttpClient-tjänsterna i serverprojektet för att göra HttpClient tillgängliga under SSR. Använd följande tjänstregistrering i serverprojektets Program-fil:

    builder.Services.AddHttpClient();
    

    HttpClient tjänster tillhandahålls av det delade ramverket, så det krävs ingen paketreferens i appens projektfil.

    Exempel: Att göra-lista webb-API i BlazorWebAppCallWebApiexempelapp

  • Om förrendering inte krävs för en WebAssembly-komponent som anropar webb-API:et inaktiverar du prerendering genom att följa anvisningarna i ASP.NET Core Blazor återgivningslägen. Om du använder den här metoden behöver du inte lägga till HttpClient-tjänster i huvudprojektet för Blazor Web App, eftersom komponenten inte är förgenererad på servern.

För mer information, se tjänster på klientsidan misslyckas med att lösas under förberedande rendering.

Förrenderade data

Vid prerendering renderas komponenter två gånger: först statiskt och sedan interaktivt. Tillståndet flödar inte automatiskt från den förrenderade komponenten till den interaktiva komponenten. Om en komponent utför asynkrona initieringsåtgärder och återger olika innehåll för olika tillstånd under initieringen, till exempel "Läser in..." kan du se ett flimmer när komponenten renderas två gånger.

Du kan åtgärda detta genom att använda förberett tillstånd med hjälp av API:et för beständiga komponenttillstånd, vilket exempelapparna BlazorWebAppCallWebApi och BlazorWebAppCallWebApi_Weather demonstrerar. När komponenten återges interaktivt kan den återges på samma sätt med samma tillstånd. API:et fungerar dock för närvarande inte med förbättrad navigering, vilket du kan kringgå genom att inaktivera förbättrad navigering på länkar till sidan (data-enhanced-nav=false). Mer information finns i följande resurser:

Lägg till tjänsten HttpClient

Vägledningen i det här avsnittet gäller för scenarier på klientsidan.

Komponenter på klientsidan anropar webb-API:er med hjälp av en förkonfigurerad HttpClient tjänst, som fokuserar på att göra begäranden tillbaka till ursprungsservern. Ytterligare HttpClient tjänstkonfigurationer för andra webb-API:er kan skapas i utvecklarkod. Begäranden skapas med hjälp av Blazor JSON-hjälp eller med HttpRequestMessage. Begäranden kan innehålla Hämta API alternativkonfiguration.

Konfigurationsexemplen i det här avsnittet är bara användbara när ett enda webb-API anropas för en enda HttpClient instans i appen. När appen måste anropa flera webb-API:er, var och en med sin egen basadress och konfiguration, kan du använda följande metoder, som beskrivs senare i den här artikeln:

I filen Program lägger du till en HttpClient-tjänst om den inte redan finns från en Blazor projektmall som används för att skapa appen:

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

I föregående exempel anges basadressen med builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), som hämtar basadressen för appen och vanligtvis härleds från <base> taggens href värde på värdsidan.

De vanligaste användningsfallen för att använda klientens egen basadress är:

  • Klientprojektet (.Client) för en Blazor Web App (.NET 8 eller senare) gör webb-API-anrop från WebAssembly-komponenter eller kod som körs på klienten i WebAssembly till API:er i serverappen.
  • Klientprojektet (Client) för en värdbaserad Blazor WebAssembly app gör webb-API-anrop till serverprojektet (Server). Observera att den värdbaserade Blazor WebAssembly projektmallen inte längre är tillgänglig i .NET 8 eller senare. Hostade Blazor WebAssembly-appar stöds dock fortfarande för .NET 8.

Om du anropar ett externt webb-API (inte i samma URL-utrymme som klientappen) anger du URI:n till webb-API:ets basadress. I följande exempel anges basadressen för webb-API:et till https://localhost:5001, där en separat webb-API-app körs och är redo att svara på begäranden från klientappen:

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

JSON-hjälpverktyg

HttpClient är tillgänglig som en förkonfigurerad tjänst för att skicka begäranden tillbaka till ursprungsservern.

HttpClient- och JSON-hjälparna (System.Net.Http.Json.HttpClientJsonExtensions) används också för att anropa webb-API-slutpunkter från tredje part. HttpClient implementeras med hjälp av webbläsarens Fetch API- och omfattas av dess begränsningar, inklusive tillämpning av principen för samma ursprung, som beskrivs senare i den här artikeln i avsnittet Resursdelning mellan ursprung (CORS).

Klientens basadress är inställd på den ursprungliga serverns adress. Mata in en HttpClient-instans i en komponent med hjälp av @inject-direktivet:

@using System.Net.Http
@inject HttpClient Http

Använd namnområdet System.Net.Http.Json för åtkomst till HttpClientJsonExtensions, inklusive GetFromJsonAsync, PutAsJsonAsyncoch PostAsJsonAsync:

@using System.Net.Http.Json

Följande avsnitt beskriver JSON-hjälparna:

System.Net.Http innehåller ytterligare metoder för att skicka HTTP-begäranden och ta emot HTTP-svar, till exempel för att skicka en DELETE-begäran. Mer information finns i avsnittet DELETE och ytterligare tilläggsmetoder.

GET från JSON (GetFromJsonAsync)

GetFromJsonAsync skickar en HTTP GET-begäran och parsar JSON-svarstexten för att skapa ett objekt.

I följande komponentkod visas todoItems av komponenten. GetFromJsonAsync anropas när komponenten har initierats (OnInitializedAsync).

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

POST som JSON (PostAsJsonAsync)

PostAsJsonAsync skickar en POST-begäran till den angivna URI:n som innehåller värdet serialiserat som JSON i begärandetexten.

I följande komponentkod tillhandahålls newItemName av ett bundet element i komponenten. Metoden AddItem utlöses genom att välja ett <button> element.

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

PostAsJsonAsync returnerar en HttpResponseMessage. Om du vill deserialisera JSON-innehållet från svarsmeddelandet använder du metoden ReadFromJsonAsync tillägg. I följande exempel läses JSON-väderdata som en matris:

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

PUT som JSON (PutAsJsonAsync)

PutAsJsonAsync skickar en HTTP PUT-begäran med JSON-kodat innehåll.

I följande komponentkod tillhandahålls editItem värden för Name och IsCompleted av bundna element i komponenten. Objektets Id anges när objektet väljs i en annan del av användargränssnittet (visas inte) och EditItem anropas. Metoden SaveItem utlöses genom att välja elementet <button>. I följande exempel visas inte inläsning av todoItems för att hålla det kort. Se avsnittet GET from JSON (GetFromJsonAsync) för ett exempel på inläsning av objekt.

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

PutAsJsonAsync returnerar en HttpResponseMessage. Om du vill deserialisera JSON-innehållet från svarsmeddelandet använder du metoden ReadFromJsonAsync tillägg. I följande exempel läser man JSON-väderdata som en array.

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

PATCH som JSON (PatchAsJsonAsync)

PatchAsJsonAsync skickar en HTTP PATCH-begäran med JSON-kodat innehåll.

Obs

Mer information finns i JsonPatch i ASP.NET Core Web API.

I följande exempel tar PatchAsJsonAsync emot ett JSON PATCH-dokument som en oformaterad textsträng med undantagna citattecken:

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

PatchAsJsonAsync returnerar en HttpResponseMessage. Om du vill deserialisera JSON-innehållet från svarsmeddelandet använder du metoden ReadFromJsonAsync tillägg. I följande exempel läser JSON todo-objektdata som en matris. En tom matris skapas om inga objektdata returneras av metoden, så content är inte null när instruktionen har körts:

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

Det okodade PATCH-dokumentet är upplagt med indrag, avstånd och okapslade citattecken och visas som följande JSON:

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

För att förenkla skapandet av PATCH-dokument i appen som utfärdar PATCH-begäranden kan en app använda .NET JSON PATCH-stöd, vilket visas i följande vägledning.

Installera Microsoft.AspNetCore.JsonPatch NuGet-paketet och använd API-funktionerna i paketet för att skapa en JsonPatchDocument för en PATCH-begäran.

Not

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

Lägg till @using-direktiv för System.Text.Json, System.Text.Json.Serializationoch Microsoft.AspNetCore.JsonPatch namnområden överst i komponenten Razor:

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

Skriv JsonPatchDocument för en TodoItem med IsComplete inställt på true med hjälp av metoden Replace:

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

Skicka dokumentets åtgärder (patchDocument.Operations) till PatchAsJsonAsync-anropet:

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

JsonSerializerOptions.DefaultIgnoreCondition anges till JsonIgnoreCondition.WhenWritingDefault för att ignorera en egenskap endast om den är lika med standardvärdet för dess typ.

Lägg till JsonSerializerOptions.WriteIndented satt till true om du vill presentera JSON-innehållet i ett tilltalande format för visning. Att skriva indragad JSON har ingen betydelse för bearbetning av PATCH-begäranden och utförs vanligtvis inte i produktionsappar för webb-API-begäranden.

Följ anvisningarna i artikeln JsonPatch i ASP.NET Core Web API för att lägga till en PATCH-kontrollantåtgärd i webb-API:et. Du kan också implementera bearbetning av PATCH-begäranden som en Minimal API- med följande steg.

Lägg till en paketreferens för Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet-paketet i webb-API-appen.

Not

Du behöver inte lägga till en paketreferens för Microsoft.AspNetCore.JsonPatch-paketet i appen eftersom referensen till Microsoft.AspNetCore.Mvc.NewtonsoftJson-paketet automatiskt lägger till en paketreferens för Microsoft.AspNetCore.JsonPatch.

I filen Program lägger du till ett @using-direktiv för Microsoft.AspNetCore.JsonPatch-namnområdet:

using Microsoft.AspNetCore.JsonPatch;

Ange slutpunkten till pipelinen för bearbetning av begäran för webb-API:et:

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

Varning

Precis som med de andra exemplen i artikeln JsonPatch i ASP.NET Core-webb-API:et skyddar inte det föregående PATCH-API:et webb-API:et från överpubliceringsattacker. För mer information, se Handledning: Skapa ett webb-API med ASP.NET Core.

En fullständigt fungerande PATCH-upplevelse kan ses i exempelappen BlazorWebAppCallWebApi.

DELETE (DeleteAsync) och ytterligare tilläggsmetoder

System.Net.Http innehåller ytterligare tilläggsmetoder för att skicka HTTP-begäranden och ta emot HTTP-svar. HttpClient.DeleteAsync används för att skicka en HTTP DELETE-begäran till ett webb-API.

I följande komponentkod anropar <button>-elementet metoden DeleteItem. Det bundna <input>-elementet tillhandahåller id för objektet som ska tas bort.

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

Namngiven HttpClient tillsammans med IHttpClientFactory

IHttpClientFactory-tjänsterna och konfigurationen av en namngiven HttpClient stöds.

Not

Ett alternativ till att använda en namngiven HttpClient från en IHttpClientFactory är att använda ett skrivet HttpClient. Mer information finns i avsnittet Typed HttpClient.

Lägg till Microsoft.Extensions.Http NuGet-paketet i appen.

Anteckning

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

I Program-filen för ett klientprojekt:

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

Om den namngivna klienten ska användas av förinstallerade komponenter på klientsidan i en Blazor Web Appbör den föregående tjänstregistreringen visas i både serverprojektet och det .Client projektet. På servern ersätts builder.HostEnvironment.BaseAddress av webb-API:ets basadress, som beskrivs nedan.

Föregående exempel på klientsidan anger basadressen med builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), som hämtar basadressen för appen på klientsidan och vanligtvis härleds från <base> taggens href värde på värdsidan.

De vanligaste användningsfallen för att använda klientens egen basadress är:

  • Klientprojektet (.Client) för en Blazor Web App som gör webb-API-anrop från WebAssembly/Automatiska komponenter eller kod som körs på klienten i WebAssembly till API:er i serverappen på samma värdadress.
  • Klientprojektet (Client) för en värdbaserad Blazor WebAssembly-app som gör webb-API-anrop till serverprojektet (Server).

Det vanligaste användningsfallet för att använda klientens egen basadress finns i klientprojektet (Client) för en värdbaserad Blazor WebAssembly app som gör webb-API-anrop till serverprojektet (Server).

Om du anropar ett externt webb-API (inte i samma URL-utrymme som klientappen) eller om du konfigurerar tjänsterna i en app på serversidan (till exempel för att hantera förrendering av komponenter på klientsidan på servern) ställer du in URI:n på webb-API:ets basadress. I följande exempel anges basadressen för webb-API:et till https://localhost:5001, där en separat webb-API-app körs och är redo att svara på begäranden från klientappen:

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

I följande komponentkod:

  • En instans av IHttpClientFactory skapar en namngiven HttpClient.
  • Det med namnet HttpClient används för att skicka en GET-begäran för väderprognos i JSON-format från webb-API:et på /forecast.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

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

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

Den BlazorWebAppCallWebApiexempelappen visar hur du anropar ett webb-API med namnet HttpClient i dess CallTodoWebApiCsrNamedClient komponent. En ytterligare arbetsdemonstration i en klientapp som baseras på att anropa Microsoft Graph med namnet HttpClientfinns i Använda Graph API med ASP.NET Core Blazor WebAssembly.

En fungerande demonstration i en klientapp som baseras på att anropa Microsoft Graph med namnet HttpClientfinns i Använda Graph API med ASP.NET Core Blazor WebAssembly.

Skrivet HttpClient

Inskrivna HttpClient använder en eller flera av appens HttpClient instanser, standard eller namngivna, för att returnera data från en eller flera webb-API-slutpunkter.

Obs

Ett alternativ till att använda en typad HttpClient är att använda ett namngivet HttpClient från en IHttpClientFactory. Mer information finns i avsnittet benämnt HttpClient med IHttpClientFactory.

Lägg till Microsoft.Extensions.Http NuGet-paketet i appen.

Obs

Mer information om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paketArbetsflöde för paketförbrukning (NuGet-dokumentation). Bekräfta rätt paketversioner på NuGet.org.

I följande exempel skickas en GET-begäran för JSON-väderprognosdata från webb-API:et på /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") ?? [];
}

I Program-filen för ett klientprojekt:

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

Om den inskrivna klienten ska användas av förinstallerade komponenter på klientsidan i en Blazor Web Appbör den föregående tjänstregistreringen visas i både serverprojektet och .Client projektet. På servern ersätts builder.HostEnvironment.BaseAddress av webb-API:ets basadress, som beskrivs nedan.

I föregående exempel anges basadressen med builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), som hämtar basadressen för appen på klientsidan och vanligtvis härleds från <base> taggens href värde på värdsidan.

De vanligaste användningsfallen för att använda klientens egen basadress är:

  • Klientprojektet (.Client) för en Blazor Web App som gör webb-API-anrop från WebAssembly/Automatiska komponenter eller kod som körs på klienten i WebAssembly till API:er i serverappen på samma värdadress.
  • Klientprojektet (Client) för en värdbaserad Blazor WebAssembly-app som gör webb-API-anrop till serverprojektet (Server).

Det vanligaste användningsfallet för att använda klientens egen basadress finns i klientprojektet (Client) för en värdbaserad Blazor WebAssembly app som gör webb-API-anrop till serverprojektet (Server).

Om du anropar ett externt webb-API (inte i samma URL-utrymme som klientappen) eller om du konfigurerar tjänsterna i en app på serversidan (till exempel för att hantera förrendering av komponenter på klientsidan på servern) ställer du in URI:n på webb-API:ets basadress. I följande exempel anges basadressen för webb-API:et till https://localhost:5001, där en separat webb-API-app körs och är redo att svara på begäranden från klientappen:

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

Komponenter matar in den typade HttpClient för att anropa webb-API:et.

I följande komponentkod:

  • En instans av föregående ForecastHttpClient matas in, vilket skapar ett skrivet HttpClient.
  • Den typerade HttpClient används för att utfärda en GET-begäran för JSON-väderprognosdata från webb-API:et.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

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

Den BlazorWebAppCallWebApiexempelappen visar hur du anropar ett webb-API med ett skrivet HttpClient i komponenten CallTodoWebApiCsrTypedClient. Observera att komponenten använder klientsideåtergivning (CSR) (InteractiveWebAssembly återgivningsläge) med för-generering, så att den typanpassade klienttjänstregistreringen visas i Program-filen för både serverprojektet och .Client-projektet.

Vägledningen i det här avsnittet gäller för scenarier på klientsidan som förlitar sig på en autentisering cookie.

För cookie-baserad autentisering, som anses vara säkrare än autentisering med ägartoken, kan cookie autentiseringsuppgifter skickas med varje webb-API-begäran genom att anropa AddHttpMessageHandler med en DelegatingHandler på en förkonfigurerad HttpClient. Hanteraren konfigurerar SetBrowserRequestCredentials med BrowserRequestCredentials.Include, som råder webbläsaren att skicka autentiseringsuppgifter med varje begäran, till exempel cookies eller HTTP-autentiseringshuvuden, inklusive för begäranden mellan ursprung.

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

CookieHandler är registrerad i filen Program:

builder.Services.AddTransient<CookieHandler>();

Meddelandehanteraren läggs till i alla förkonfigurerade HttpClient som kräver cookie autentisering:

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

När du skapar en HttpRequestMessageanger du webbläsarens begärans autentiseringsuppgifter och huvud direkt.

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

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

HttpClient och HttpRequestMessage med alternativ för hämtning av API-begäran

Vägledningen i det här avsnittet gäller för scenarier på klientsidan som förlitar sig på ägartokenautentisering.

HttpClient (API-dokumentation) och HttpRequestMessage kan användas för att anpassa begäranden. Du kan till exempel ange HTTP-metoden och begärandehuvuden. Följande komponent gör en POST begäran till en webb-API-slutpunkt och visar svarstexten.

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

Blazorimplementering på klientsidan av HttpClient använder Fetch API och konfigurerar de underliggande programspecifika hämtnings-API-alternativ via HttpRequestMessage tilläggsmetoder och WebAssemblyHttpRequestMessageExtensions. Ange ytterligare alternativ med hjälp av den generiska SetBrowserRequestOption-tilläggsmetoden. Blazor och det underliggande Fetch API:et lägger inte till eller ändrar inte begärandehuvuden direkt. Mer information om hur användaragenter, till exempel webbläsare, interagerar med rubriker finns i dokumentationsuppsättningar för externa användaragenter och andra webbresurser.

HTTP-svaret buffrar vanligtvis för att aktivera stöd för synkrona läsningar i svarsinnehållet. Om du vill aktivera stöd för strömning av svar använder du SetBrowserResponseStreamingEnabled-tilläggsmetoden på förfrågan.

För att inkludera referenser i en begäran om korsande ursprung, använd tilläggsmetoden SetBrowserRequestCredentials:

requestMessage.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Mer information om alternativ för Fetch API finns i MDN-webbdokumentation: WindowOrWorkerGlobalScope.fetch(): Parametrar.

Felhantering

Hantera webb-API-svarsfel i utvecklarkod när de inträffar. GetFromJsonAsync förväntar sig till exempel ett JSON-svar från webb-API:et med en Content-Type av application/json. Om svaret inte är i JSON-format genererar innehållsvalidering en NotSupportedException.

I följande exempel är URI-slutpunkten för databegäran för väderprognos felstavad. URI:n bör vara att WeatherForecast men visas i anropet som WeatherForcast, som saknar bokstaven e i Forecast.

GetFromJsonAsync-anropet förväntar sig att JSON returneras, men webb-API:et returnerar HTML för ett ohanterat undantag med en Content-Type av text/html. Det ohanterade undantaget inträffar eftersom sökvägen till /WeatherForcast inte hittas och mellanprogramvara inte kan leverera en sida eller vy för begäran.

I OnInitializedAsync på klientsidan genereras NotSupportedException när svarsinnehållet valideras som icke-JSON. Undantaget fångas i blocket catch, där anpassad logik kan logga felet eller visa ett användarvänligt felmeddelande för användaren.

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

Not

Föregående exempel är i demonstrationssyfte. Ett webb-API kan konfigureras för att returnera JSON även när en slutpunkt inte finns eller ett ohanterat undantag inträffar på servern.

Mer information finns i Hantera fel i ASP.NET Core Blazor-appar.

Resursdelning mellan ursprung (CORS)

Webbläsarsäkerhet begränsar ofta en webbsida från att göra begäranden till ett annat ursprung än den som betjänade webbsidan. Den här begränsningen kallas princip för samma ursprung. Principen för samma ursprung begränsar (men förhindrar inte) att en skadlig webbplats läser känsliga data från en annan webbplats. Om du vill göra begäranden från webbläsaren till en slutpunkt med ett annat ursprung måste slutpunkt aktivera CORS (Cross-Origin Resource Sharing).

Mer information om CORS på serversidan finns i Aktivera CORS (Cross-Origin Requests) i ASP.NET Core. Artikelns exempel gäller inte direkt för Razor komponentscenarier, men artikeln är användbar för att lära sig allmänna CORS-begrepp.

Information om CORS-begäranden på klientsidan finns i ASP.NET Core Blazor WebAssembly ytterligare säkerhetsscenarier.

Stöd mot förfalskning

Om du vill lägga till stöd för antiforgery i en HTTP-begäran matar du in AntiforgeryStateProvider och lägger till en RequestToken i rubriksamlingen som en 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);
    ...
}

Mer information finns i ASP.NET Core Blazor-autentisering och auktorisering.

Blazor ramverkskomponentexempel för testning av webb-API-åtkomst

Olika nätverksverktyg är offentligt tillgängliga för att testa webb-API-serverdelsappar direkt, till exempel Firefox Browser Developer. Blazor ramverkets referenskälla innehåller HttpClient testtillgångar som är användbara för testning:

HttpClientTest tillgångar på dotnet/aspnetcore GitHub-lagringsplatsen

Not

Dokumentationslänkar till .NET-referenskällan läser vanligtvis in lagringsplatsens standardgren, vilket representerar den aktuella utvecklingen för nästa version av .NET. Om du vill välja en tagg för en specifik version använder du listrutan Växla grenar eller taggar. Mer information finns i Så här väljer du en versionstagg för ASP.NET Core-källkod (dotnet/AspNetCore.Docs #26205).

Ytterligare resurser

Allmänt

Minskning av överpostningsattacker

Webb-API:er kan vara sårbara för en överpublicering attack, även kallat en masstilldelning attack. En överpubliceringsattack inträffar när en obehörig användare utfärdar ett HTML-formulär POST till servern som bearbetar data för egenskaper som inte ingår i det renderade formuläret och som utvecklaren inte vill tillåta användare att ändra. Termen "överposting" innebär bokstavligen att den skadliga användaren har skickat via-POST med formuläret.

Vägledning om hur du åtgärdar överpubliceringsattacker finns i Självstudie: Skapa ett webb-API med ASP.NET Core.

Serversidan

Klientsidan