Dela via


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

Note

Det här är inte den senaste versionen av den här artikeln. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Warning

Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .

Important

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.

För den nuvarande utgåvan, se .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.

Package

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.

Använda en tokenhanterare för webb-API-anrop

Blazor Web Apps med OIDC-autentisering kan använda en metod för tokenhanterare för att göra utgående begäranden för att skydda externa webb-API-anrop. Den här metoden används av exempelapparna BlazorWebAppOidc och BlazorWebAppOidcServer som beskrivs i avsnittet Exempelappar i den här artikeln.

Mer information finns i följande resurser:

Microsofts identitetsplattform för webb-API-anrop

Blazor Web Apps som använder Microsoft identity platform med Microsoft Identity Web packages för Microsoft Entra ID kan göra strömlinjeformade webb-API-anrop med API som tillhandahålls av Microsoft.Identity.Web.DownstreamApi NuGet-paketet.

Note

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

Ange en grundläggande URL och omfång i appinställningsfilen (appsettings.json). I följande exempel {BASE ADDRESS} är platshållaren bas-URL:en för webb-API:et. Ett enda åtkomstomfång anges med en App-ID-URI ({APP ID URI} platshållare) och omfångsnamn ({SCOPE NAME} platshållare):

"DownstreamApi": {
  "BaseUrl": "{BASE ADDRESS}",
  "Scopes": [ "{APP ID URI}/{SCOPE NAME}" ]
}

Example:

"DownstreamApi": {
  "BaseUrl": "https://localhost:7277",
  "Scopes": [ "api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get" ]
}

I appens Program fil anropar du:

Du kan välja att kryptera cachen och bör alltid göra det i produktion.

builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddDownstreamApi("DownstreamApi", 
        builder.Configuration.GetSection("DownstreamApi"))
    .AddDistributedTokenCaches();

// Requires the 'Microsoft.Extensions.Caching.Memory' NuGet package
builder.Services.AddDistributedMemoryCache();

builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
    options => 
    {
        // The following lines that are commented out reflect
        // default values. We recommend overriding the default
        // value of Encrypt to encrypt tokens at rest.

        //options.DisableL1Cache = false;
        //options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
        options.Encrypt = true;
        //options.SlidingExpiration = TimeSpan.FromHours(1);
    });

Minnesinterna distribuerade tokencacher skapas vid anrop av AddDistributedTokenCaches för att säkerställa att det finns en basimplementering tillgänglig för cachelagring av distribuerade token.

Produktionswebbappar och webb-API:er bör använda en cache för distribuerad token för produktion (till exempel : Redis, Microsoft SQL Server, Microsoft Azure Cosmos DB).

Note

För lokal utveckling och testning på en enda dator kan du använda minnesinterna tokencacheminnen i stället för distribuerade tokencacheminnen:

builder.Services.AddInMemoryTokenCaches();

Senare under utvecklings- och testperioden ska du anta en produktionsinriktad leverantör för distribuerad tokencache.

AddDistributedMemoryCache lägger till en standardimplementering av IDistributedCache som lagrar cacheobjekt i minnet, som används av Microsoft Identity Web för cachelagring av token.

AddDistributedMemoryCache kräver en paketreferens till Microsoft.Extensions.Caching.Memory NuGet-paketet.

Note

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

Information om hur du konfigurerar en distribuerad cacheprovider för produktion finns i Distribuerad cachelagring i ASP.NET Core.

Warning

Ersätt alltid de in-memory distribuerade tokens med en riktig tokencacheprovider när du levererar appen till en produktionsmiljö. Om du inte kan använda en leverantör av distribuerad tokencache för produktion kan appen få avsevärt sämre prestanda.

Mer information finns i Token cache serialisering: Distribuerade cacheminnen. De kodexempel som visas gäller dock inte för ASP.NET Core-appar som konfigurerar distribuerade cacheminnen via AddDistributedMemoryCache, inte AddDistributedTokenCache.

Använd en delad dataskyddsnyckelring i produktion så att instanser av appen över servrar i en webbserverfarm kan dekryptera tokenen när MsalDistributedTokenCacheAdapterOptions.Encrypt är inställd på true.

Note

För tidig utveckling och lokal testning på en enda dator kan du ange Encrypt till false och konfigurera en delad dataskyddsnyckelring senare:

options.Encrypt = false;

Senare under utvecklings- och testperioden aktiverar du tokenkryptering och antar en delad dataskyddsnyckelring.

I följande exempel visas hur du använder Azure Blob Storage och Azure Key Vault (PersistKeysToAzureBlobStorage/ProtectKeysWithAzureKeyVault) för den delade nyckelringen. Tjänstkonfigurationerna är basfallsscenarier i demonstrationssyfte. Innan du distribuerar produktionsappar kan du bekanta dig med Azure-tjänsterna och använda metodtips med hjälp av Azure-tjänsternas dedikerade dokumentationsuppsättningar, som är länkade i slutet av det här avsnittet.

Lägg till följande paket i serverprojektet för Blazor Web App:

Note

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

Note

Innan du fortsätter med följande steg kontrollerar du att appen är registrerad hos Microsoft Entra.

Konfigurera Azure Blob Storage för att underhålla dataskyddsnycklar. Följ riktlinjerna i Nyckellagringsprovidrar i ASP.NET Core.

Konfigurera Azure Key Vault för att kryptera de vilande dataskyddsnycklarna. Följ riktlinjerna i Konfigurera ASP.NET Core Data Protection.

Använd följande kod i Program filen där tjänster är registrerade:

TokenCredential? credential;

if (builder.Environment.IsProduction())
{
    credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
    // Local development and testing only
    DefaultAzureCredentialOptions options = new()
    {
        // Specify the tenant ID to use the dev credentials when running the app locally
        // in Visual Studio.
        VisualStudioTenantId = "{TENANT ID}",
        SharedTokenCacheTenantId = "{TENANT ID}"
    };

    credential = new DefaultAzureCredential(options);
}

builder.Services.AddDataProtection()
    .SetApplicationName("{APPLICATION NAME}")
    .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
    .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);

{MANAGED IDENTITY CLIENT ID}: Azure Hanterad Identity Klient-ID (GUID).

{TENANT ID}: Hyresgäst-ID.

{APPLICATION NAME}: SetApplicationName anger det unika namnet på den här appen i dataskyddssystemet. Värdet ska matcha mellan distributioner av appen.

{BLOB URI}: Fullständig URI till nyckelfilen. URI:n genereras av Azure Storage när du skapar nyckelfilen. Använd inte en SAS.

{KEY IDENTIFIER}: Azure Key Vault-nyckelidentifierare som används för nyckelkryptering. Med en åtkomstprincip kan programmet komma åt nyckelvalvet med Getbehörigheterna , Unwrap Keyoch Wrap Key . Nyckelidentifieraren hämtas från nyckeln i Entra- eller Azure-portalen när den har skapats. Om du aktiverar autorotation av nyckelvalvsnyckeln kontrollerar du att du använder en versionslös nyckelidentifierare i appens nyckelvalvskonfiguration, där inget nyckel-GUID placeras i slutet av identifieraren (exempel: https://contoso.vault.azure.net/keys/data-protection).

Note

I miljöer som inte är produktionsmiljöer används DefaultAzureCredential föregående exempel för att förenkla autentiseringen vid utveckling av appar som distribueras till Azure genom att kombinera autentiseringsuppgifter som används i Azure-värdmiljöer med autentiseringsuppgifter som används i lokal utveckling. När du går över till produktion är ett annat alternativ ett bättre val, som ManagedIdentityCredential som visas i det föregående exemplet. Mer information finns i Autentisera Azure-hostade .NET-appar till Azure-resurser med en systemtilldelad hanterad identitet.

Mata in IDownstreamApi och anropa CallApiForUserAsync när du anropar för en användares räkning:

internal sealed class ServerWeatherForecaster(IDownstreamApi downstreamApi) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        var response = await downstreamApi.CallApiForUserAsync("DownstreamApi",
            options =>
            {
                options.RelativePath = "/weather-forecast";
            });

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

Den här metoden används av exempelapparna BlazorWebAppEntra och BlazorWebAppEntraBff som beskrivs i avsnittet Exempelappar i den här artikeln.

Mer information finns i följande resurser:

Exempelappar

Exempel finns i följande exempelappar i exempellagringsplatsenBlazor för GitHub () (dotnet/blazor-samplesså här laddar du ned).

BlazorWebAppCallWebApi

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

  • Backend: En webb-API-app för att underhålla en att göra-lista baserat på minimala API:er. 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 ett internt filmlistnings-API inom Blazor Web App, vars API 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 filmlisteåtgärder baserat på minimala 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();
}

Mer information om hur du skyddar filmdata i det här scenariot finns i exemplet med väderdata som beskrivs av Säkra data i Blazor Web Apps med interaktiv automatisk återgivning.

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-app för att underhålla en att göra-lista baserat på minimala API:er.
  • 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.

BlazorWebAssemblyStandaloneWithIdentity

En fristående Blazor WebAssembly app som skyddas med ASP.NET Core Identity:

  • Backend: En webb-API-app för serverdelen som underhåller ett användaridentitetsarkiv för ASP.NET Core Identity.
  • BlazorWasmAuth: En fristående Blazor WebAssembly klientdelsapp med användarautentisering.

Lösningen visar hur du anropar ett säkert webb-API för följande:

  • Hämta roller för en autentiserad användare.
  • Databearbetning för alla autentiserade användare.
  • Databearbetning för behöriga användare (användaren måste vara i Manager rollen) via en auktoriseringsprincip.

BlazorWebAppOidc

En Blazor Web App med global automatisk interaktivitet som använder OIDC-autentisering med Microsoft Entra utan att använda Entra-specifika paket. Exemplet visar hur du använder en tokenhanterare för webb-API-anrop för att anropa ett externt säkert webb-API.

BlazorWebAppOidcServer

En Blazor Web App med global interaktiv serverinteraktivitet som använder OIDC-autentisering med Microsoft Entra utan att använda Entra-specifika paket. Exemplet visar hur du skickar en åtkomsttoken för att anropa ett externt säkert webb-API.

BlazorWebAppOidcBff

En Blazor Web App med global autointeraktivitet som använder:

  • OIDC-autentisering med Microsoft Entra utan att använda Entra-specifika paket.
  • BFF-mönstret (Backend for Frontend), som är ett mönster för apputveckling som skapar serverdelstjänster för klientdelsappar eller gränssnitt.

Lösningen innehåller en demonstration av att hämta väderdata på ett säkert sätt via ett externt webb-API när en komponent som implementerar interaktiv automatisk återgivning återges på klienten.

BlazorWebAppEntra

A Blazor Web App med global autointeraktivitet som använder Microsofts identitetsplattform med Microsoft-webbpaket Identity för Microsoft Entra-ID. Lösningen innehåller en demonstration av att hämta väderdata på ett säkert sätt via ett externt webb-API när en komponent som implementerar interaktiv automatisk återgivning återges på klienten.

BlazorWebAppEntraBff

En Blazor Web App med global autointeraktivitet som använder:

Lösningen innehåller en demonstration av att hämta väderdata på ett säkert sätt via ett externt webb-API när en komponent som implementerar interaktiv automatisk återgivning återges på klienten.

Avyttring av HttpRequestMessage, HttpResponseMessageoch HttpClient

En HttpRequestMessage utan en brödtext kräver inte explicit bortskaffande med en using deklaration (C# 8 eller senare) eller ett using block (alla C#-versioner), men vi rekommenderar att du bortser från varje användning av följande skäl:

  • För att få en prestandaförbättring genom att undvika finalizers.
  • Det förstärker koden för framtiden om en begärandetext läggs till i ett HttpRequestMessage som inte ursprungligen hade en.
  • För att eventuellt undvika funktionella problem om en delegerande hanterare förväntar sig ett anrop till Dispose/DisposeAsync.
  • Det är enklare att tillämpa en allmän regel överallt än att försöka komma ihåg specifika fall.

Ta alltid bort HttpResponseMessage instanser.

Ta aldrig bort HttpClient instanser som skapats genom att anropa CreateClient eftersom de hanteras av ramverket.

Example:

using var request = new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
var client = clientFactory.CreateClient("ExternalApi");
using var response = await client.SendAsync(request);

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 gör en begäran till ett webb-API för GitHub-grenar, liknande exemplet Grundläggande användning i artikeln Gör HTTP-begäranden 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()
    {
        using 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");

        using 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>()).

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

Blazor WebAssemblyappar hindras ofta från att göra direkta anrop mellan ursprung till webb-API:er på grund av CORS-säkerhet (Cross-Origin Request Sharing). Ett typiskt undantag ser ut så här:

Åtkomst för att hämta från {URL} från ursprunget {c0}; har blockerats av CORS-policy: Ingen "Access-Control-Allow-Origin"-header 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:t som du anropar tillåter din ursprungsdomän att anropa sitt ursprung med rätt 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{REQUEST URI} är platshållaren URI:n för begäran:

    @using System.Net
    @inject IHttpClientFactory ClientFactory
    
    ...
    
    @code {
        public async Task CallApi()
        {
            var client = ClientFactory.CreateClient();
    
            var urlEncodedRequestUri = WebUtility.UrlEncode("{REQUEST URI}");
    
            using var request = new HttpRequestMessage(HttpMethod.Get, 
                $"https://corsproxy.io/?{urlEncodedRequestUri}");
    
            using 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 med hjälp av fabriksinfrastrukturenHttpClient.

I filen Program:

builder.Services.AddHttpClient();

Följande Razor-komponent gör en begäran till ett webb-API för GitHub-grenar, liknande exemplet Grundläggande användning i artikeln Gör HTTP-begäranden 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()
    {
        using 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();

        using 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-filuppladdningarBlazor.

Tjänstabstraktioner för webb-API-anrop

Det här avsnittet gäller för Blazor Web Apps som 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 Prerender ASP.NET Core-komponenterRazor.

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 Skydda en ASP.NET Core Blazor Web App med OpenID Connect (OIDC).

Blazor Web App externa webb-APIer

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

Blazor Web Appförbereder vanligtvis WebAssembly-komponenter på klientsidan, och Auto-komponenter renderas på servern under statisk eller interaktiv serverå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 HttpClient i avsnittet Lägg till tjänst , 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 någon 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: Webb-API för att-göra-lista i BlazorWebAppCallWebApiexempelappen

  • Om förrendering inte krävs för en WebAssembly-komponent som anropar webb-API:et inaktiverar du prerendering genom att följa riktlinjerna i Prerender ASP.NET Core-komponenterRazor. 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.

Mer information finns i avsnittet klientsidstjänster kan inte lösas under prerendering i artikeln Prerendering.

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. Mer information finns i följande resurser:

Note

API:et för beständiga komponenttillstånd stöder endast förbättrad navigering i .NET 10 eller senare. För appar som riktar in sig på .NET 8 eller .NET 9 kan du inaktivera utökad navigering på länkar till sidan med data-enhance-nav attributet inställt på false. Mer information finns i ASP.NET Core-routning Blazor och navigering.

Direktuppspelning av begäranden på klientsidan

För Chromium-baserade webbläsare (till exempel Google Chrome och Microsoft Edge) med hjälp av HTTP/2-protokollet och HTTPS använder klientsidan BlazorStreams API för att tillåta strömning av begäranden.

Om du vill aktivera strömning av begäranden anger du SetBrowserRequestStreamingEnabled till trueHttpRequestMessage.

I följande exempel på filuppladdning:

using var request = new HttpRequestMessage(HttpMethod.Post, "/Filesave");
request.SetBrowserRequestStreamingEnabled(true);
request.Content = content;

using var response = await Http.SendAsync(request);

Direktuppspelningsbegäranden:

  • Kräv HTTPS-protokoll och fungerar inte på HTTP/1.x.
  • Inkludera en brödtext men inte en Content-Length rubrik. CORS med en förhandsbegäran krävs för begäranden om direktuppspelning mellan ursprung.

Mer information om filuppladdningar med en InputFile komponent finns i ASP.NET Core-filuppladdningar Blazor och exemplet på Ladda upp filer till en server med återgivning på klientsidan (CSR).

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 inkludera Fetch 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 projektmallen Hosted Blazor WebAssembly 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. HttpClientimplementeras 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 ett 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 enkelhetens skull. Se avsnittet GET från JSON (GetFromJsonAsync) för ett exempel på inläsning av objekt.

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

PutAsJsonAsync returnerar ett 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>();

PATCH som JSON (PatchAsJsonAsync)

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

Note

Mer information finns i JsonPatch i ASP.NET Core-webb-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}]");

Från och med C# 11 (.NET 7) kan du komponera en JSON-sträng som en råsträngslitteral. Ange JSON-syntaxen med StringSyntaxAttribute.Json-fältet som motsvarar [StringSyntax]-attributet för kodanalysverktyg:

@using System.Diagnostics.CodeAnalysis

...

@code {
    [StringSyntax(StringSyntaxAttribute.Json)]
    private const string patchOperation =
        """[{"operationType":2,"path":"/IsComplete","op":"replace","value":true}]""";

    ...

    await Http.PatchAsJsonAsync($"todoitems/{id}", patchOperation);
}

PatchAsJsonAsync returnerar ett 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:

using 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.SystemTextJson NuGet-paketet och använd API-funktionerna i paketet för att skapa en JsonPatchDocument för en PATCH-begäran.

Note

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet 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.Serialization- och Microsoft.AspNetCore.JsonPatch.SystemTextJson-namnrymderna överst i Razor-komponenten.

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

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

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

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.

Note

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet 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);

Överför 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 lättläst 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 riktlinjerna 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 ett minimalt API med följande steg.

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

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

using Microsoft.AspNetCore.JsonPatch.SystemTextJson;

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

Note

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

Warning

Precis som med de andra exemplen i artikeln JsonPatch i ASP.NET Core Web API skyddar inte det föregående PATCH-API:et webb-API:et från överpubliceringsattacker. Mer information finns i Självstudie: Skapa ett kontrollantbaserat 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.

Note

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 Typat HttpClient.

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

Note

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet 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") ?? [];
    }
}

Exempelappen BlazorWebAppCallWebApi visar hur du anropar ett webb-API med ett namngivet i dess komponent HttpClient. För en ytterligare arbetsdemonstration i en klientapp baserad på att anropa Microsoft Graph med ett namngivet HttpClient, se 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.

Note

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 Namngivna HttpClient med IHttpClientFactory .

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

Note

Vägledning om hur du lägger till paket i .NET-appar finns i artiklarna under Installera och hantera paket i arbetsflödet 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 typsatta klienten ska användas av förrenderade komponenter på klientsidan i en Blazor Web App, bör den tidigare 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 typat 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();
    }
}

BlazorWebAppCallWebApi visar hur du anropar ett webb-API med en typsatt HttpClient i dess CallTodoWebApiCsrTypedClient-komponent. Observera att komponenten använder rendering på klientsidan (CSR) ( återgivningsläge) med för-rendering , så att den inskrivna klienttjänstregistreringen visas i -filen i både serverprojektet och -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);
    }
}

Note

Information om hur du får åtkomst till en AuthenticationStateProvider från en DelegatingHandlerfinns i ASP.NET Core-serversidan och Blazor Web App ytterligare säkerhetsscenarier.

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

För en demonstration, se skydda ASP.NET Core Blazor WebAssembly med ASP.NET Core Identity.

När du skapar en HttpRequestMessage, ange webbläsarens begärans autentiseringsuppgifter och huvudrubrik direkt.

using var request = new HttpRequestMessage() { ... };

request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);
request.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å autentisering med ägartoken.

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()
    {
        using var request = 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))
        {
            request.Headers.Authorization =
                new AuthenticationHeaderValue("Bearer", token.Value);

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

            using var response = await Http.SendAsync(request);
            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; }
    }
}

Blazor's implementering på klientsidan av HttpClient använder Fetch API och konfigurerar de underliggande begärandespecifika hämtnings-API-alternativen 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.

Svarsströmning är aktiverat som standard.

Anropa HttpContent.ReadAsStreamAsync för en HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) returnerar en BrowserHttpReadStream (referenskälla), inte en MemoryStream. BrowserHttpReadStream stöder inte synkrona åtgärder, till exempel Stream.Read(Span<Byte>). Om koden använder synkrona åtgärder kan du välja bort strömning av svar eller kopiera Stream till en MemoryStream själv.

Note

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).

Om du vill välja bort strömning av svar globalt använder du någon av följande metoder:

  • Lägg till egenskapen <WasmEnableStreamingResponse> i projektfilen med värdet false:

    <WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
    
  • DOTNET_WASM_ENABLE_STREAMING_RESPONSE Ange miljövariabeln till false eller 0.

Om du vill välja bort strömning av svar för en enskild begäran anger du SetBrowserResponseStreamingEnabled till falseHttpRequestMessage (request i följande exempel):

request.SetBrowserResponseStreamingEnabled(false);

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 anger du SetBrowserResponseStreamingEnabled till trueHttpRequestMessage:

request.SetBrowserResponseStreamingEnabled(true);

Som standard anges HttpCompletionOption.ResponseContentRead, vilket resulterar i att HttpClient slutförs efter att hela svaret har lästs, inklusive innehållet. För att kunna använda alternativet SetBrowserResponseStreamingEnabled på stora filer ställer du in HttpCompletionOption.ResponseHeadersRead för att undvika att cachelagra filens innehåll i minnet:

- using var response = await Http.SendAsync(request);
+ using var response = await Http.SendAsync(request, 
+     HttpCompletionOption.ResponseHeadersRead);

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

request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Mer information om hämtning av API-alternativ finns i MDN-webbdokument: WindowOrWorkerGlobalScope.fetch(): Parametrar.

Hantering av fel

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 där en Content-Typetext/html förekommer. 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;
        }
    }
}

Note

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-apparBlazor.

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 principen 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 slutpunkten 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 för att skydda 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();
    using var request = new HttpRequestMessage(HttpMethod.Post, "action");
    request.Headers.Add("RequestVerificationToken", antiforgery.RequestToken);
    using var response = await client.SendAsync(request);
    ...
}

Mer information finns i ASP.NET Core-autentisering Blazor 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:

HttpClientTesttillgångar på GitHub-lagringsplatsen dotnet/aspnetcore

Note

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

General

Minskning av överpostningsattacker

Webb-API:er kan vara sårbara för en överpubliceringsattack , även kallat en masstilldelningsattack . 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 "över-POST:ande" innebär att den skadliga användaren kan ha överanvänt POST-metoden med formuläret.

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

Server-side

Client-side