Sdílet prostřednictvím


Volání webového rozhraní API z ASP.NET Core Blazor

Note

Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.

Warning

Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Pro aktuální vydání si přečtěte verzi článku pro .NET 9.

Tento článek popisuje, jak volat webové API z Blazor aplikace.

Package

Balíček System.Net.Http.Json poskytuje rozšiřující metody pro System.Net.Http.HttpClient a System.Net.Http.HttpContent, které provádějí automatickou serializaci a deserializaci pomocí System.Text.Json. Balíček System.Net.Http.Json poskytuje sdílená architektura .NET a nevyžaduje přidání odkazu na balíček do aplikace.

Použijte zpracovač tokenu pro volání webového rozhraní API

Blazor Web Apps s autentizací OIDC mohou použít přístup správce tokenu k vytváření odchozích požadavků na zabezpečení volání externích webových API. Tento přístup používají BlazorWebAppOidc ukázkové BlazorWebAppOidcServer aplikace popsané v části Ukázkové aplikace tohoto článku.

Další informace naleznete v následujících zdrojích:

Microsoft Identity Platform pro volání webového rozhraní API

Blazor Web Apps, které používají Microsoft identity platform s webovými balíčky společnosti Microsoft Identity pro Microsoft Entra ID, mohou zjednodušit volání webového rozhraní API pomocí rozhraní API poskytovaného balíčkem NuGetMicrosoft.Identity.Web.DownstreamApi.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

V souboru nastavení aplikace (appsettings.json) zadejte základní adresu URL a obory. V následujícím příkladu {BASE ADDRESS} je zástupný symbol základní adresou URL webového rozhraní API. Jeden obor se zadává pomocí identifikátoru URI ID aplikace ({APP ID URI} zástupný symbol) a názvu oboru ({SCOPE NAME} zástupný symbol):

"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" ]
}

V souboru aplikace Program zavolejte:

Můžete se rozhodnout zašifrovat mezipaměť a vždy to udělat v produkčním prostředí.

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

Při volání AddDistributedTokenCaches se vytvoří mezipaměti distribuovaných tokenů v paměti, aby byla k dispozici základní implementace pro ukládání do mezipaměti distribuovaných tokenů.

Produkční webové aplikace a webová rozhraní API by měly používat mezipaměť produkčních distribuovaných tokenů (například Redis, Microsoft SQL Server, Microsoft Azure Cosmos DB).

Note

Pro místní vývoj a testování na jednom počítači můžete místo mezipamětí distribuovaných tokenů použít mezipaměti tokenů v paměti:

builder.Services.AddInMemoryTokenCaches();

Později ve vývojovém a testovacím období použijte poskytovatele produkční mezipaměti pro distribuované tokeny.

AddDistributedMemoryCache přidá výchozí implementaci IDistributedCache , která ukládá položky mezipaměti do paměti, která je používána webem Společnosti Microsoft Identity pro ukládání tokenů do mezipaměti.

AddDistributedMemoryCache vyžaduje odkaz na Microsoft.Extensions.Caching.Memory balíček NuGet.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Pokud chcete nakonfigurovat zprostředkovatele produkční distribuované mezipaměti, přečtěte si téma Distribuované ukládání do mezipaměti v ASP.NET Core.

Warning

Při nasazování aplikace do produkčního prostředí vždy nahraďte mezipaměti distribuovaných tokenů v paměti skutečným poskytovatelem mezipaměti tokenů. Pokud nepoužijete produkční poskytovatele distribuovaného token cache, může být výkon aplikace výrazně snížen.

Další informace naleznete v tématu Serializace mezipaměti tokenů: Distribuované mezipaměti. Uvedené příklady kódu se však nevztahují na aplikace ASP.NET Core, které konfigurují distribuované mezipaměti prostřednictvím AddDistributedMemoryCache, nikoli AddDistributedTokenCache.

Použijte sdílený kruh klíčů ochrany dat v produkčním prostředí, aby instance aplikace na serverech ve webové farmě mohly dešifrovat tokeny, když je MsalDistributedTokenCacheAdapterOptions.Encrypt nastavena na true.

Note

Pro počáteční vývoj a místní testování na jednom počítači můžete nastavit Encryptfalse a nakonfigurovat sdílený okruh klíčů ochrany dat později:

options.Encrypt = false;

Později ve vývojovém a testovacím období povolte šifrování tokenů a přijměte sdílený okruh klíčů ochrany dat.

Následující příklad ukazuje, jak používat Azure Blob Storage a Azure Key Vault (PersistKeysToAzureBlobStorage/ProtectKeysWithAzureKeyVault) pro okruh sdíleného klíče. Konfigurace služby jsou základní modelové scénáře pro demonstrační účely. Před nasazením produkčních aplikací se seznamte se službami Azure a využijte osvědčené postupy s využitím vyhrazených sad dokumentace služeb Azure, které jsou propojené na konci této části.

Přidejte do projektu Blazor Web Appserveru následující balíčky:

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Note

Než budete pokračovat v následujících krocích, ověřte, že je aplikace zaregistrovaná v Microsoft Entra.

Nakonfigurujte službu Azure Blob Storage tak, aby uchovávala klíče ochrany dat. Postupujte podle pokynů v poskytovatelích úložiště klíčů v ASP.NET Core.

Nakonfigurujte Azure Key Vault pro šifrování neaktivních uložených klíčů ochrany dat. Postupujte podle pokynů v tématu Konfigurace ASP.NET Základní ochrana dat.

V souboru, Program ve kterém jsou zaregistrované služby, použijte následující kód:

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}: ID spravovaného Identity klienta Azure (GUID).

{TENANT ID}: ID nájemce.

{APPLICATION NAME}: SetApplicationName Nastaví jedinečný název této aplikace v rámci systému ochrany dat. Hodnota by se měla shodovat mezi nasazeními aplikace.

{BLOB URI}: Úplný identifikátor URI souboru klíče. Identifikátor URI se vygeneruje službou Azure Storage při vytváření souboru klíče. Nepoužívejte SAS.

{KEY IDENTIFIER}: Identifikátor klíče služby Azure Key Vault používaný k šifrování klíčů. Zásady přístupu umožňují aplikaci přistupovat k trezoru klíčů pomocí GetUnwrap KeyWrap Key a oprávnění. Identifikátor klíče se získá z klíče na webu Entra nebo Azure portálu po jeho vytvoření. Pokud povolíte automatickou rotaci klíče trezoru klíčů, ujistěte se, že v konfiguraci klíčového trezoru aplikace používáte identifikátor bez verzování, kde na konci identifikátoru není uveden žádný GUID klíče (například: https://contoso.vault.azure.net/keys/data-protection).

Note

V neprodukčních prostředích se předchozí příklad používá DefaultAzureCredential ke zjednodušení ověřování při vývoji aplikací, které se nasazují do Azure zkombinováním přihlašovacích údajů používaných v hostitelských prostředích Azure s přihlašovacími údaji použitými v místním vývoji. Při přechodu na produkční prostředí je lepší volbou alternativa, například znázorněná ManagedIdentityCredential v předchozím příkladu. Další informace najdete v tématu Ověřování aplikací .NET hostovaných v Azure v prostředcích Azure pomocí spravované identity přiřazené systémem.

Vložte IDownstreamApi a volejte CallApiForUserAsync při volání jménem uživatele:

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

Tento přístup používají BlazorWebAppEntra ukázkové BlazorWebAppEntraBff aplikace popsané v části Ukázkové aplikace tohoto článku.

Další informace naleznete v následujících zdrojích:

Ukázkové aplikace

Pracovní příklady najdete v následujících ukázkových aplikacích v úložišti GitHub s ukázkami Blazor (dotnet/blazor-samples) (jak stáhnout).

BlazorWebAppCallWebApi

Zavolejte externí webové API seznamu úkolů (které není v Blazor Web App) z Blazor Web App:

  • Backend: Aplikace pro správu seznamu úkolů využívající Minimal APIs. Webová API aplikace je oddělenou aplikací od Blazor Web App a možná je hostována na jiném serveru.
  • BlazorApp / BlazorApp.Client: Blazor Web App, který volá webovou aplikaci API pro operace se seznamem HttpClient úkolů, jako je vytváření, čtení, aktualizace a mazání položek (CRUD) v seznamu úkolů.

Pro vykreslování na straně klienta (CSR), které zahrnuje interaktivní komponenty WebAssembly a automatické komponenty, které přijaly CSR, se provádějí volání s předem nakonfigurovaným HttpClient zaregistrovaným v Program souboru klientského projektu (BlazorApp.Client):

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

Pro vykreslování na straně serveru (SSR), které zahrnuje předrenderované a interaktivní komponenty serveru, předrenderované komponenty WebAssembly a automatické komponenty, které jsou buď předem renderované, nebo přijaly SSR, se volání provádějí s HttpClient registrovaným v Program souboru serverového projektu (BlazorApp):

builder.Services.AddHttpClient();

Zahájit volání interního rozhraní API seznamu filmů (uvnitř Blazor Web App), které se nachází v serverovém projektu Blazor Web App.

  • BlazorApp: Blazor Web App, který udržuje seznam filmů:
    • Při provádění operací v seznamu filmů v aplikaci na serveru se použijí běžná volání rozhraní API.
    • Když webový klient provádí volání rozhraní API, použije se webové rozhraní API pro operace se seznamem filmů na základě minimálních rozhraní API.
  • BlazorApp.Client: Klientský projekt Blazor Web App, který obsahuje interaktivní WebAssembly a automatické komponenty pro správu uživatelů seznamu filmů.

Pro CSR, která zahrnuje interaktivní komponenty WebAssembly a automatické komponenty, které přijaly CSR, se volání rozhraní API provádí prostřednictvím služby založené na klientovi (ClientMovieService), která používá předkonfigurovaný zaregistrovaný HttpClient v Program souboru klientského projektu (BlazorApp.Client). Vzhledem k tomu, že se tato volání provádějí přes veřejný nebo privátní web, je API seznamu filmů webové API.

Následující příklad získá seznam filmů z koncového /movies bodu:

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

Pro rozhraní SSR, které zahrnují předem vykreslené a interaktivní komponenty serveru, předem vykreslené komponenty WebAssembly a automatické komponenty, které jsou buď předem vykreslené, nebo používají SSR, se volání provádějí přímo prostřednictvím serverové služby (ServerMovieService). Rozhraní API nespoléhá na síť, takže se jedná o standardní rozhraní API pro operace CRUD seznamu filmů.

Následující příklad získá seznam filmů:

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

Další informace o tom, jak zabezpečit filmová data v tomto scénáři, najdete v příkladu dat o počasí popsaném v části Zabezpečení dat v systému Blazor Web Apps interaktivním automatickým vykreslováním.

BlazorWebAppCallWebApi_Weather

Ukázková aplikace dat o počasí, která používá vykreslování streamovaných dat pro data o počasí.

BlazorWebAssemblyCallWebApi

Volá webové API seznamu úkolů z aplikace Blazor WebAssembly.

  • Backend: Aplikace pro správu seznamu úkolů využívající Minimal APIs.
  • BlazorTodo: Blazor WebAssembly aplikace, která volá webové API s předem nakonfigurovanými operacemi CRUD pro seznam úkolů.

BlazorWebAssemblyStandaloneWithIdentity

Samostatná aplikace Blazor WebAssembly zabezpečená pomocí IdentityASP.NET Core:

  • Backend: Aplikace back-endového webového rozhraní API, která udržuje úložiště identit uživatelů pro ASP.NET Core Identity.
  • BlazorWasmAuth: Samostatná Blazor WebAssembly front-endová aplikace s ověřováním uživatelů.

Řešení ukazuje volání zabezpečeného webového rozhraní API pro následující:

  • Získání rolí autentizovaného uživatele
  • Zpracování dat pro všechny ověřené uživatele
  • Zpracování dat pro oprávněné uživatele (uživatel musí být v roli Manager) prostřednictvím politiky autorizace .

BlazorWebAppOidc

Zařízení Blazor Web App s globální automatickou interaktivitou, které používá OIDC autentizaci s Microsoft Entra, aniž by používalo balíčky specifické pro Entra. Ukázka ukazuje , jak použít obslužnou rutinu tokenu pro volání webového rozhraní API pro volání externího zabezpečeného webového rozhraní API.

BlazorWebAppOidcServer

A Blazor Web App s globální interaktivitou Interactive Server, který používá OIDC autentizaci s Microsoft Entra bez použití Entra-specifických balíčků. Ukázka ukazuje, jak předat přístupový token pro volání externího zabezpečeného webového rozhraní API.

BlazorWebAppOidcBff

Blazor Web App s globální automatickou interaktivitou, která používá:

  • Ověřování OIDC s Microsoft Entra bez použití balíčků specifických pro Entra.
  • Model Backend pro Frontend (BFF), což je vzor vývoje aplikací, který vytváří back-endové služby pro front-endové aplikace nebo rozhraní.

Řešení obsahuje ukázku bezpečného získání dat o počasí prostřednictvím externího webového rozhraní API, když je na klientu vykreslena komponenta používající Interactive Auto rendering.

BlazorWebAppEntra

A Blazor Web App s globální interaktivitou Auto, která používá Microsoft identity platform s Microsoft Identity Web packages pro Microsoft Entra ID. Řešení obsahuje ukázku bezpečného získání dat o počasí prostřednictvím externího webového rozhraní API, když je na klientu vykreslena komponenta používající Interactive Auto rendering.

BlazorWebAppEntraBff

Blazor Web App s globální automatickou interaktivitou, která používá:

Řešení obsahuje ukázku bezpečného získání dat o počasí prostřednictvím externího webového rozhraní API, když je na klientu vykreslena komponenta používající Interactive Auto rendering.

Likvidace HttpRequestMessage, HttpResponseMessage a HttpClient

HttpRequestMessage bez těla nevyžaduje explicitní odstranění. Můžete ho však odstranit některým z následujících vzorů:

K každému použití doporučujeme zlikvidovat každou HttpRequestMessage z následujících důvodů:

  • Pokud chcete dosáhnout zlepšení výkonu, vyhněte se finalizačním metodám.
  • V případě, že se tělo požadavku někdy přidá do HttpRequestMessage objektu, který ho původně neměl, zpevní kód pro budoucnost.
  • Chcete-li potenciálně zabránit funkčním problémům, pokud delegující obslužná rutina očekává volání Dispose/DisposeAsync.
  • Je jednodušší použít obecné pravidlo všude, než si vzpomenout na konkrétní případy.

Vždy odstraňte HttpResponseMessage instance.

Nikdy nelikvidujte HttpClient instance vytvořené voláním CreateClient , protože jsou spravovány architekturou.

Example:

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

Scénáře na straně klienta pro volání externích webových rozhraní API

Klientské komponenty volají externí webová API pomocí instancí HttpClient, které se obvykle vytvářejí pomocí předem nakonfigurovaného HttpClient, zaregistrovaného v souboru Program.

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

Následující Razor komponenta vytvoří požadavek na webové rozhraní API pro větve GitHubu podobně jako příklad základního použití v článku 'Vytváření požadavků HTTP pomocí IHttpClientFactory v 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; }
    }
}

V předchozím příkladu pro C# 12 a vyšší se vytvoří prázdné pole ([]) pro proměnnou branches. Pro starší verze jazyka C# zkompilované pomocí sady SDK starší než .NET 8 vytvořte prázdné pole (Array.Empty<GitHubBranch>()).

K ochraně kódu a dat .NET/C# použijte funkce ASP.NET Core Data Protection s back-endovým webovým rozhraním API na straně serveru ASP.NET Core. Klientská Blazor WebAssembly aplikace volá webové rozhraní API na straně serveru pro zabezpečené funkce aplikací a zpracování dat.

Blazor WebAssembly aplikacím se často brání v přímém volání z jednoho původu na jiný k webovým API kvůli sdílení zdrojů mezi různými originy (CORS) zabezpečení. Typická výjimka vypadá takto:

Přístup k načtení z adresy {URL} z původu 'https://localhost:{PORT}'' byl zablokován zásadami CORS: U požadovaného prostředku není přítomna hlavička 'Access-Control-Allow-Origin'. Pokud pro vaše potřeby stačí neprůhledná odpověď, nastavte režim požadavku na 'no-cors', aby se prostředek načítal se zakázaným CORS.

I když voláte SetBrowserRequestMode s polem BrowserRequestModeNoCors (1) snažícím se obejít předchozí výjimku, požadavek často selže kvůli omezením CORS u původu webového API, jako je omezení, které povoluje pouze volání z určitých původů, nebo omezení, které zabraňuje JavaScriptovým fetch požadavkům z prohlížeče. Jediný způsob, jak uspět s těmito voláními, je, aby webové API, které voláte, umožnilo zdroji vaší stránky volat jeho zdroj se správnou konfigurací CORS. Většina externích webových rozhraní API neumožňuje konfigurovat jejich zásady CORS. Pokud chcete toto omezení vyřešit, použijte některou z následujících strategií:

  • Udržujte si vlastní back-endové webové rozhraní API na straně serveru ASP.NET Core. Klientská aplikace Blazor WebAssembly volá webové rozhraní API na straně serveru a vaše webové rozhraní API odešle požadavek z kódu C# založeného na serveru (ne z prohlížeče) na externí webové rozhraní API se správnými hlavičkami CORS a vrátí výsledek do vaší aplikace na straně klienta Blazor WebAssembly.

  • Proxy služba slouží k proxy požadavku z klientské Blazor WebAssembly aplikace do externího webového rozhraní API. Proxy služba používá aplikaci na straně serveru k vytvoření požadavku jménem klienta a vrátí výsledek po úspěšném volání. V následujícím příkladu založeném na CloudFlare's CORS PROXY, je zástupný symbol {REQUEST URI} identifikátor URI požadavku:

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

Scénáře na straně serveru pro volání externích webových rozhraní API

Serverové komponenty volají externí webová rozhraní API pomocí HttpClient instancí, obvykle vytvořených pomocí IHttpClientFactory. Pokyny, které platí pro aplikace na straně serveru, najdete v tématu Vytváření požadavků HTTP pomocí IHttpClientFactory v ASP.NET Core.

Aplikace na straně serveru nezahrnuje HttpClient službu. Poskytněte HttpClient aplikaci využitím infrastruktury HttpClient továrny.

V souboru Program:

builder.Services.AddHttpClient();

Následující Razor komponenta vytvoří požadavek na webové rozhraní API pro větve GitHubu podobně jako příklad základního použití v článku 'Vytváření požadavků HTTP pomocí IHttpClientFactory v 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; }
    }
}

V předchozím příkladu pro C# 12 a vyšší se vytvoří prázdné pole ([]) pro proměnnou branches. Pro starší verze jazyka C# zkompilované pomocí sady SDK starší než .NET 8 vytvořte prázdné pole (Array.Empty<GitHubBranch>()).

Další funkční příklad najdete v článku o nahrávání souborů v ASP.NET Core, kde je uveden příklad nahrání souboru na straně serveru do kontroleru webového rozhraní API.

Abstrakce služby pro volání webového rozhraní API

Tato část se vztahuje na Blazor Web App, které zajišťují webové rozhraní API v serverovém projektu nebo transformují volání webového rozhraní API na externí webové rozhraní API.

Při použití interaktivního režimu WebAssembly a automatického vykreslení jsou komponenty standardně předem vygenerovány. Komponenty Auto se také zpočátku interaktivně vykreslují ze serveru před stažením balíčku Blazor do klienta a aktivací modulu runtime na straně klienta. To znamená, že komponenty používající tyto režimy vykreslování by měly být navrženy tak, aby se úspěšně spouštěly z klienta i ze serveru. Pokud komponenta musí při spuštění na klientovi volat serverové projektové rozhraní API nebo transformovat požadavek na externí webové rozhraní API (které jsou mimo Blazor Web App), doporučuje se toto volání rozhraní API abstrahovat za rozhraním služby a implementovat klientské a serverové verze služby.

  • Verze klienta volá webové rozhraní API s předkonfigurovaným HttpClient.
  • Verze serveru má obvykle přímý přístup k prostředkům na straně serveru. Vložení HttpClient na server, které vyžaduje volání zpět na server, se nedoporučuje, protože síťový požadavek je obvykle zbytečný. Alternativně může být rozhraní API externí vůči serverovému projektu, ale pro server je vyžadována abstrakce služby, která transformuje požadavek nějakým způsobem, například přidáním přístupového tokenu k zprostředkované žádosti.

Při použití režimu vykreslování WebAssembly máte také možnost zakázat předběžné vykreslování, takže komponenty se vykreslují pouze z klienta. Další informace naleznete v tématu Prerender ASP.NET Core Razor komponenty.

Příklady (ukázkové aplikace):

  • Webové rozhraní API seznamu filmů v BlazorWebAppCallWebApi ukázkové aplikaci
  • Streamování webového rozhraní API pro zpracování dat o počasí v ukázkové aplikaci.
  • Data o počasí vrácená klientovi v ukázkových aplikacích buď s použitím BlazorWebAppOidc (vzor ne-BFF) nebo BlazorWebAppOidcBff (vzor BFF). Tyto aplikace demonstrují zabezpečená (webová) volání rozhraní API. Další informace najdete v tématu Zabezpečení ASP.NET Core Blazor Web App pomocí OpenID Connect (OIDC).

Blazor Web App externí webová rozhraní API

Tato část se týká Blazor Web Appvolání webového rozhraní API spravovaného samostatným (externím) projektem, který je pravděpodobně hostovaný na jiném serveru.

Blazor Web Apps obvykle předkreslují komponenty WebAssembly na straně klienta a Auto komponenty se vykreslují na serveru během statického nebo interaktivního server-side renderování (SSR). HttpClient služby nejsou ve výchozím nastavení zaregistrované v Blazor Web Apphlavním projektu. Pokud je aplikace spuštěna pouze se službami HttpClient zaregistrovanými v projektu .Client, jak je popsáno v části Přidat službu HttpClient, spuštění aplikace způsobí chybu za běhu:

cs-CZ: InvalidOperationException: Nelze poskytnout hodnotu pro vlastnost 'Http' typu '...{COMPONENT}'. Neexistuje žádná registrovaná služba typu System.Net.Http.HttpClient.

Použijte některý z následujících přístupů:

  • Přidejte služby HttpClient do projektu serveru, aby bylo HttpClient dostupné během SSR. V souboru projektu serveru Program použijte následující registraci služby:

    builder.Services.AddHttpClient();
    

    HttpClient služby jsou poskytovány sdílenou architekturou, takže není vyžadován odkaz na balíček v souboru projektu aplikace.

    Příklad: Webové rozhraní API seznamu úkolů v BlazorWebAppCallWebApiukázkové aplikaci

  • Pokud se pro komponentu WebAssembly, která volá webové rozhraní API, nevyžaduje prerendering, zakažte předběžné předkreslování podle pokynů v komponentách Prerender ASP.NET CoreRazor. Pokud tento přístup přijmete, nemusíte do hlavního HttpClient projektu přidávat Blazor Web App služby, protože tato komponenta není na serveru předem označená.

Další informace najdete v části Služby na straně klienta, které se nepodaří vyřešit během předdefinování části článku Prerendering .

Předem renderovaná data

Při předkreslování se komponenty vykreslují dvakrát: nejprve staticky a interaktivně. Stav automaticky neprochází z předem vykreslené komponenty do interaktivní komponenty. Pokud komponenta provádí asynchronní inicializační operace a během inicializace vykresluje různý obsah pro různé stavy, například indikátor průběhu "Načítání...", může dojít k blikání, když se komponenta vykreslí dvakrát.

Tento problém můžete vyřešit použitím toku předem vykresleného stavu pomocí API pro stav přetrvávající komponenty, což demonstrují BlazorWebAppCallWebApi a BlazorWebAppCallWebApi_Weatherukázkové aplikace. Když se komponenta vykreslí interaktivně, bude se vykreslovat způsobem odpovídajícím danému stavu. Další informace naleznete v následujících zdrojích:

Note

API pro přetrvávající stav komponent podporuje rozšířenou navigaci pouze v .NET 10 nebo novějším. U aplikací, které cílí na .NET 8 nebo .NET 9, můžete zakázat rozšířenou navigaci u odkazů na stránku s atributem nastaveným data-enhance-nav na false. Další informace najdete v tématu ASP.NET Blazor Základní směrování a navigace.

Streamování požadavků na straně klienta

V prohlížečích založených na Chromiu (například Google Chrome a Microsoft Edge), které používají protokol HTTP/2 a HTTPS, klientská strana Blazor používá Streams API k umožnění streamování žádostí.

Pokud chcete povolit streamování požadavků, nastavte SetBrowserRequestStreamingEnabled na true v HttpRequestMessage.

V následujícím příkladu nahrání souboru:

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

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

Požadavky na streamování:

  • Vyžaduje protokol HTTPS a nepodporuje HTTP/1.x.
  • Zahrňte text, ale ne hlavičku Content-Length. CORS s pre-flight požadavkem je nutný pro streamovací požadavky mezi různými zdroji.

Další informace o nahrávání souborů s komponentou InputFile naleznete v tématu ASP.NET Core Blazor nahrávání souborů a příklad viz na Nahrání souborů na server s vykreslováním na straně klienta (CSR).

Přidat službu HttpClient

Pokyny v této části platí pro scénáře na straně klienta.

Komponenty na straně klienta volají webová rozhraní API pomocí předkonfigurované HttpClient služby, která se zaměřuje na provádění požadavků zpět na server původu. V kódu pro vývojáře je možné vytvořit další HttpClient konfigurace služby pro jiná webová rozhraní API. Žádosti se skládají pomocí Blazor pomocných rutin JSON nebo pomocí HttpRequestMessage. Požadavky můžou zahrnovat konfiguraci možností Fetch API.

Příklady konfigurace v této části jsou užitečné jenom v případě, že se pro jednu instanci v aplikaci volá jedno HttpClient webové rozhraní API. Když aplikace musí volat více webových rozhraní API, každá s vlastní základní adresou a konfigurací, můžete přijmout následující přístupy, které jsou popsány dále v tomto článku:

Program V souboru přidejte HttpClient službu, pokud ještě není k dispozici ze Blazor šablony projektu použité k vytvoření aplikace:

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

Předchozí příklad nastaví základní adresu pomocí builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), což určuje základní adresu aplikace a obvykle se odvozuje z hodnoty značky <base>href na hostitelské stránce.

Nejběžnější případy použití pro použití vlastní základní adresy klienta jsou:

  • Projekt klienta .Client (.NET 8 nebo novější) provádí volání webových API z komponentů nebo kódu WebAssembly, které běží na straně klienta v prostředí WebAssembly, do rozhraní API v serverové aplikaci.
  • Klientský projekt (Client) hostované aplikace Blazor WebAssembly provádí webové volání API k serverovému projektu (Server). Všimněte si, že šablona hostovaného Blazor WebAssembly projektu už není v rozhraní .NET 8 nebo novější dostupná. Hostované Blazor WebAssembly aplikace ale zůstávají podporované pro .NET 8.

Pokud voláte externí webové rozhraní API (ne ve stejném prostoru adres URL jako klientská aplikace), nastavte identifikátor URI na základní adresu webového rozhraní API. Následující příklad nastaví základní adresu webového rozhraní API na https://localhost:5001, kde je spuštěná samostatná webová aplikace API a připravená reagovat na požadavky z klientské aplikace:

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

Pomocné nástroje JSON

HttpClient je k dispozici jako předkonfigurovaná služba pro provádění požadavků zpět na původní server.

HttpClient a JSON pomocníci (System.Net.Http.Json.HttpClientJsonExtensions) se také používají k volání koncových bodů webového rozhraní API třetích stran. HttpClient se implementuje pomocí rozhraní Fetch API prohlížeče a podléhá jeho omezením, včetně zásad stejného původu, které jsou popsány dále v tomto článku v části Sdílení prostředků mezi zdroji (CORS).

Základní adresa klienta je nastavená na adresu původního serveru. Vložte HttpClient instance do komponenty pomocí @inject direktivy:

@using System.Net.Http
@inject HttpClient Http

System.Net.Http.Json Použití oboru názvů pro přístup k HttpClientJsonExtensions, včetně GetFromJsonAsync, PutAsJsonAsync a PostAsJsonAsync:

@using System.Net.Http.Json

Následující části zahrnují pomocníky JSON.

System.Net.Http obsahuje další metody pro odesílání požadavků HTTP a přijímání odpovědí HTTP, například pro odeslání požadavku DELETE. Další informace najdete v části DELETE a další metody pro rozšíření.

GET z JSONu (GetFromJsonAsync)

GetFromJsonAsync odešle požadavek HTTP GET a parsuje tělo odpovědi JSON k vytvoření objektu.

V následujícím kódu jsou todoItems zobrazeny komponentou. GetFromJsonAsync je volána po dokončení inicializace komponenty (OnInitializedAsync).

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

POST as JSON (PostAsJsonAsync)

PostAsJsonAsync odešle požadavek POST na zadaný identifikátor URI obsahující hodnotu serializovanou jako JSON v těle požadavku.

V následujícím kódu komponenty je newItemName poskytována vázaným prvkem dané komponenty. Metoda AddItem se aktivuje výběrem elementu <button> .

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

PostAsJsonAsync vrátí hodnotu HttpResponseMessage. Použijte rozšiřující metodu ReadFromJsonAsync pro deserializaci obsahu JSON ze zprávy odpovědi. Následující příklad čte data o počasí JSON jako pole:

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

PUT as JSON (PutAsJsonAsync)

PutAsJsonAsync odešle požadavek HTTP PUT s obsahem kódovaným ve formátu JSON.

V následujícím kódu komponenty editItem jsou hodnoty pro Name a IsCompleted poskytovány prvky vázanými ke komponentě. Položka Id je nastavena, když je položka vybrána v jiné části uživatelského rozhraní (není zobrazena) a EditItem je volána. Metoda SaveItem se aktivuje výběrem elementu <button> . Následující příklad nezobrazuje načítání todoItems pro stručnost. Příklad načítání položek najdete v části GET z JSON (GetFromJsonAsync).

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

PutAsJsonAsync vrátí hodnotu HttpResponseMessage. Použijte rozšiřující metodu ReadFromJsonAsync pro deserializaci obsahu JSON ze zprávy odpovědi. Následující příklad čte data o počasí JSON jako pole:

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

PATCH as JSON (PatchAsJsonAsync)

PatchAsJsonAsync odešle požadavek HTTP PATCH s obsahem kódovaným ve formátu JSON.

Note

Další informace najdete v tématu JsonPatch ve webovém rozhraní API ASP.NET Core.

V následujícím příkladu PatchAsJsonAsync obdrží dokument JSON PATCH jako řetězec prostého textu s escapovanými uvozovkami.

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

Od jazyka C# 11 (.NET 7) můžete vytvořit řetězec JSON jako nezpracovaný řetězec. Zadejte syntaxi JSON s polem StringSyntaxAttribute.Json do atributu [StringSyntax] pro nástroje pro analýzu kódu:

@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 vrátí hodnotu HttpResponseMessage. Použijte rozšiřující metodu ReadFromJsonAsync pro deserializaci obsahu JSON ze zprávy odpovědi. Následující příklad načítá data položek úkolů ve formátu JSON jako pole. Pokud metoda nevrací žádná data položek, vytvoří se prázdné pole, takže content po provedení příkazu není null:

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

Rozložen s odsazením, mezerami a nezakódovanými uvozovkami, nekódovaný dokument PATCH se jeví jako následující JSON:

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

Pro zjednodušení vytváření dokumentů PATCH v aplikaci vydávajících požadavky PATCH může aplikace používat podporu .NET JSON PATCH, jak ukazuje následující doprovodné materiály.

Microsoft.AspNetCore.JsonPatch.SystemTextJson Nainstalujte balíček NuGet a pomocí funkcí rozhraní API balíčku JsonPatchDocument vytvořte požadavek PATCH.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Přidejte @using direktivy pro System.Text.Json, System.Text.Json.Serializationa Microsoft.AspNetCore.JsonPatch.SystemTextJson obory názvů na začátek Razor komponenty:

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

Sestavte JsonPatchDocument pro TodoItem s nastavením IsComplete na true pomocí metody JsonPatchDocument.Replace

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

Microsoft.AspNetCore.JsonPatch Nainstalujte balíček NuGet a pomocí funkcí rozhraní API balíčku JsonPatchDocument vytvořte požadavek PATCH.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Přidejte @using direktivy pro System.Text.Json, System.Text.Json.Serialization a Microsoft.AspNetCore.JsonPatch obory názvů na začátek komponenty Razor.

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

Sestavte JsonPatchDocument pro TodoItem s nastavením IsComplete na true pomocí metody Replace

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

Předejte operace dokumentu (patchDocument.Operations) na PatchAsJsonAsync volání:

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

JsonSerializerOptions.DefaultIgnoreCondition je nastavena tak, aby JsonIgnoreCondition.WhenWritingDefault ignorovala vlastnost pouze v případě, že se rovná výchozí hodnotě pro jeho typ.

Pokud chcete prezentovat datovou část JSON v příjemném formátu pro zobrazení, přidejte JsonSerializerOptions.WriteIndented sadu true. Zápis odsazeného formátu JSON nemá žádný vliv na zpracování požadavků PATCH a obvykle se neprovádí v produkčních aplikacích pro požadavky webového rozhraní API.

Pokud chcete do webového rozhraní API přidat akci kontroleru PATCH, postupujte podle pokynů v článku JsonPatch v ASP.NET core webovém rozhraní API. Případně je možné zpracování požadavků PATCH implementovat jako minimální rozhraní API pomocí následujícího postupu.

Přidejte odkaz na Microsoft.AspNetCore.JsonPatch.SystemTextJson balíček NuGet do aplikace webového rozhraní API.

Do souboru Program přidejte direktivu @using pro obor názvů Microsoft.AspNetCore.JsonPatch.SystemTextJson.

using Microsoft.AspNetCore.JsonPatch.SystemTextJson;

Přidejte odkaz na Microsoft.AspNetCore.Mvc.NewtonsoftJson balíček NuGet do aplikace webového rozhraní API.

Note

Není nutné do aplikace přidat odkaz na balíček Microsoft.AspNetCore.JsonPatch, protože odkaz na balíček Microsoft.AspNetCore.Mvc.NewtonsoftJson automaticky tranzitivně přidá odkaz na balíček Microsoft.AspNetCore.JsonPatch.

Do souboru Program přidejte direktivu @using pro obor názvů Microsoft.AspNetCore.JsonPatch.

using Microsoft.AspNetCore.JsonPatch;

Zadejte koncový bod kanálu zpracování požadavků webového rozhraní API:

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

Warning

Stejně jako u ostatních příkladů v článku JsonPatch v ASP.NET Core web API nechrání uvedené PATCH API webové rozhraní API před útoky typu over-posting. Další informace najdete v tématu Kurz: Vytvoření webového rozhraní API založeného na kontroleru s ASP.NET Core.

Plně funkční prostředí PATCH najdete v BlazorWebAppCallWebApiukázkové aplikaci.

DELETE (DeleteAsync) a další rozšiřující metody

System.Net.Http obsahuje další metody rozšíření pro odesílání požadavků HTTP a přijímání odpovědí HTTP. HttpClient.DeleteAsync slouží k odeslání požadavku HTTP DELETE do webového rozhraní API.

V následujícím kódu komponenty volá prvek <button> metodu DeleteItem. Vázaný <input> prvek poskytuje id položky k odstranění.

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

Pojmenované HttpClient pomocí IHttpClientFactory

IHttpClientFactory jsou podporovány služby a konfigurace pojmenovaného HttpClient.

Note

Alternativou k použití pojmenovaného HttpClient z IHttpClientFactory je použití typovaného HttpClient. Další informace najdete v části Typed.HttpClient

Přidejte do Microsoft.Extensions.Http aplikace balíček NuGet.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Program V souboru klientského projektu:

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

Pokud se má pojmenovaný klient používat komponentami na straně klienta předem renderovanými Blazor Web App, měla by se předchozí registrace služby objevit jak v projektu serveru, tak v projektu .Client. Na serveru builder.HostEnvironment.BaseAddress se nahrazuje základní adresou webového rozhraní API, která je popsána níže.

Předchozí příklad na straně klienta nastaví základní adresu s builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), která získává základní adresu pro aplikaci na straně klienta a obvykle je odvozena z hodnoty značky <base> na hostitelské stránce.

Nejběžnější případy použití pro použití vlastní základní adresy klienta jsou:

  • Projekt klienta (.Client), který provádí volání webového Blazor Web App rozhraní API z komponent nebo kódu WebAssembly/Auto běžícího na klientovi do API v aplikačním serveru na stejné hostitelské adrese.
  • Klientský projekt (Client) hostované Blazor WebAssembly aplikace, která provádí volání webového rozhraní API do projektu serveru (Server).

Nejběžnější případ použití pro použití vlastní základní adresy klienta je v klientském projektu (Client) hostované Blazor WebAssembly aplikace, která provádí volání webového rozhraní API do projektu serveru (Server).

Pokud voláte externí webové rozhraní API (ne ve stejném prostoru adres URL jako klientská aplikace) nebo konfigurujete služby v aplikaci na straně serveru (například pro řešení předběžného nastavení komponent na straně klienta na serveru), nastavte identifikátor URI na základní adresu webového rozhraní API. Následující příklad nastaví základní adresu webového rozhraní API na https://localhost:5001, kde je spuštěná samostatná webová aplikace API a připravená reagovat na požadavky z klientské aplikace:

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

V následujícím kódu komponenty:

  • Instance IHttpClientFactory vytvoří pojmenovanou HttpClient.
  • HttpClient se používá k vydání GET požadavku na JSON data s předpovědí počasí z webového API na adrese /forecast.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

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

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

Ukázková BlazorWebAppCallWebApiaplikace ukazuje volání webového rozhraní API s názvem HttpClient ve své CallTodoWebApiCsrNamedClient komponentě. Další funkční ukázku v klientské aplikaci založenou na volání Microsoft Graphu s názvem HttpClientnajdete v tématu Použití rozhraní Graph API s ASP.NET Core Blazor WebAssembly.

Funkční ukázku v klientské aplikaci založenou na volání Microsoft Graphu s názvem HttpClientnajdete v tématu Použití rozhraní Graph API s ASP.NET Core Blazor WebAssembly.

Psaný na stroji HttpClient

Typed HttpClient používá k vrácení dat z jednoho nebo více koncových bodů webového rozhraní API jednu nebo více instancí aplikace HttpClient ( výchozí nebo pojmenované).

Note

Alternativou k použití zadaného typu HttpClient je použití pojmenovaného HttpClient z objektu IHttpClientFactory. Další informace najdete v sekci Pojmenované HttpClient s IHttpClientFactory.

Přidejte do Microsoft.Extensions.Http aplikace balíček NuGet.

Note

Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.

Následující příklad vydává požadavek GET na data předpovědi počasí JSON z webového rozhraní API na adrese /forecast.

ForecastHttpClient.cs:

using System.Net.Http.Json;

namespace BlazorSample.Client;

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

Program V souboru klientského projektu:

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

Pokud je typový klient používán předem vykreslovanými komponentami Blazor Web App na straně klienta, měla by se předchozí registrace služby objevit jak v projektu serveru, tak v projektu .Client. Na serveru builder.HostEnvironment.BaseAddress se nahrazuje základní adresou webového rozhraní API, která je popsána níže.

Předchozí příklad nastaví základní adresu na builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), která získá základní adresu pro aplikaci na straně klienta a obvykle je odvozena z hodnoty značky <base> v tagu href na hostitelské stránce.

Nejběžnější případy použití pro použití vlastní základní adresy klienta jsou:

  • Projekt klienta (.Client), který provádí volání webového Blazor Web App rozhraní API z komponent nebo kódu WebAssembly/Auto běžícího na klientovi do API v aplikačním serveru na stejné hostitelské adrese.
  • Klientský projekt (Client) hostované Blazor WebAssembly aplikace, která provádí volání webového rozhraní API do projektu serveru (Server).

Nejběžnější případ použití pro použití vlastní základní adresy klienta je v klientském projektu (Client) hostované Blazor WebAssembly aplikace, která provádí volání webového rozhraní API do projektu serveru (Server).

Pokud voláte externí webové rozhraní API (ne ve stejném prostoru adres URL jako klientská aplikace) nebo konfigurujete služby v aplikaci na straně serveru (například pro řešení předběžného nastavení komponent na straně klienta na serveru), nastavte identifikátor URI na základní adresu webového rozhraní API. Následující příklad nastaví základní adresu webového rozhraní API na https://localhost:5001, kde je spuštěná samostatná webová aplikace API a připravená reagovat na požadavky z klientské aplikace:

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

Komponenty vkládají typ HttpClient, aby bylo možné volat webové API.

V následujícím kódu komponenty:

  • Instance předchozího ForecastHttpClient je vložena, což vytvoří typ HttpClient.
  • Zadaný HttpClient se používá k odeslání GET požadavku na JSON předpověď počasí z webového API.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

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

Ukázková BlazorWebAppCallWebApiaplikace ukazuje volání webového rozhraní API s typem HttpClient v jeho CallTodoWebApiCsrTypedClient komponentě. Všimněte si, že komponenta přijímá vykreslování na straně klienta (CSR) (InteractiveWebAssemblyrežim vykreslování) s předběžným vykreslováním, takže se v souboru serverového projektu i Program projektu zobrazí .Client registrace zadané klientské služby.

Pokyny v této části platí pro scénáře na straně klienta, které spoléhají na ověřování cookie.

Pro cookieověřování založené na, které je považováno za bezpečnější než ověření tokenu, je možné odesílat přihlašovací údaje s každou žádostí webového rozhraní API voláním cookie s AddHttpMessageHandler na předkonfigurovaném DelegatingHandler. Obslužná rutina nastavuje SetBrowserRequestCredentials s BrowserRequestCredentials.Include tak, aby prohlížeč posílal přihlašovací údaje s jednotlivými požadavky, jako jsou soubory cookie nebo hlavičky ověřování HTTP, včetně požadavků mezi zdroji.

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

Pro pokyny k tomu, jak přistupovat k AuthenticationStateProvider z DelegatingHandler, viz ASP.NET Core na straně serveru a Blazor Web App další scénáře zabezpečení.

Soubor CookieHandler je zaregistrovaný v souboru Program :

builder.Services.AddTransient<CookieHandler>();

Zpracovatel zpráv se přidá do libovolného předkonfigurovaného objektu HttpClient, který vyžaduje cookie ověření.

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

Ukázku najdete v tématu Zabezpečení ASP.NET Core Blazor WebAssembly s ASP.NET Core Identity.

Při vytváření HttpRequestMessage požadavku prohlížeče nastavte přihlašovací údaje a hlavičku přímo:

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

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

HttpClient a HttpRequestMessage s možnostmi požadavku Fetch API

Pokyny v této části platí pro scénáře na straně klienta, které spoléhají na ověřování nosných tokenů.

HttpClient (Dokumentace k rozhraní API) a HttpRequestMessage lze ji použít k přizpůsobení požadavků. Můžete například zadat metodu HTTP a hlavičky požadavku. Následující komponenta odešle POST požadavek na koncový bod webového rozhraní API a zobrazí text odpovědi.

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

BlazorImplementace HttpClient rozhraní API na straně klienta používá rozhraní Fetch API a konfiguruje základní možnosti rozhraní Fetch API specifické pro požadavky prostřednictvím HttpRequestMessage rozšiřujících metod a WebAssemblyHttpRequestMessageExtensions. Nastavte další možnosti pomocí obecné SetBrowserRequestOption metody rozšíření. Blazor a rozhraní Fetch API přímo nepřidává ani neupravuje hlavičky požadavků. Další informace o tom, jak uživatelé agenti, jako jsou prohlížeče, pracují se záhlavími, najdete v dokumentaci externích uživatelských agentů a dalších webových prostředcích.

Streamování odpovědí je ve výchozím nastavení povolené.

Volání HttpContent.ReadAsStreamAsync pro HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) vrátí BrowserHttpReadStream (odkazový zdroj), nikoli MemoryStream. BrowserHttpReadStream nepodporuje synchronní operace, například Stream.Read(Span<Byte>). Pokud váš kód používá synchronní operace, můžete se rozhodnout nepoužívat streamování odpovědí nebo zkopírovat Stream do MemoryStream sami.

Note

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Pokud chcete vyjádřit výslovný nesouhlas se streamováním odpovědí globálně, použijte některý z následujících přístupů:

  • <WasmEnableStreamingResponse> Přidejte vlastnost do souboru projektu s hodnotou false:

    <WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
    
  • Nastavte proměnnou DOTNET_WASM_ENABLE_STREAMING_RESPONSE prostředí na false hodnotu nebo 0.

Pokud chcete vyjádřit výslovný nesouhlas se streamováním odpovědí pro jednotlivé požadavky, nastavte SetBrowserResponseStreamingEnabled na false na HttpRequestMessage (request v následujícím příkladu):

request.SetBrowserResponseStreamingEnabled(false);

Odpověď HTTP je obvykle uložena do vyrovnávací paměti, aby bylo možné povolit podporu synchronních čtení v obsahu odpovědi. Pokud chcete povolit podporu streamování odpovědí, nastavte SetBrowserResponseStreamingEnabled na true :HttpRequestMessage

request.SetBrowserResponseStreamingEnabled(true);

Ve výchozím nastavení je HttpCompletionOption.ResponseContentRead nastaveno, což vede k tomu, že HttpClient se dokončí po přečtení celé odpovědi včetně obsahu. Pokud chcete, aby bylo možné použít SetBrowserResponseStreamingEnabled možnost u velkých souborů, nastavte HttpCompletionOption.ResponseHeadersRead , aby se zabránilo ukládání obsahu souboru do mezipaměti v paměti:

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

Pro zahrnutí přihlašovacích údajů do požadavku mezi zdroji použijte metodu rozšíření SetBrowserRequestCredentials.

request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Další informace o možnostech rozhraní API pro načítání najdete ve webové dokumentaci MDN: WindowOrWorkerGlobalScope.fetch(): Parametry.

Řešte chyby

Zpracování chyb odpovědí webového rozhraní API v kódu vývojáře při jejich výskytu Například GetFromJsonAsync očekává odpověď ve formátu JSON z webového rozhraní API obsahující Content-Typeapplication/json. Pokud odpověď není ve formátu JSON, ověření obsahu vyvolá NotSupportedExceptionchybu .

V následujícím příkladu je koncový bod identifikátoru URI pro požadavek na data předpovědi počasí chybně napsaný. Identifikátor URI by měl být ve volání jako WeatherForecast, ale chybí mu písmeno WeatherForcast v e.

Volání GetFromJsonAsync očekává návrat JSON, ale webové rozhraní API vrátí HTML pro neošetřenou výjimku s Content-Typetext/html. Neošetřená výjimka nastane, protože cesta /WeatherForcast nebyla nalezena, a middleware nemůže pro daný požadavek obsluhovat ani zobrazit stránku.

Ve OnInitializedAsync na klientovi je NotSupportedException vyhozen, když je obsah odpovědi ověřen jako ne-JSON. Výjimka se zachytí v catch bloku, kde vlastní logika může chybu protokolovat nebo uživateli zobrazit popisnou chybovou zprávu.

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

Předchozí příklad je určený pro demonstrační účely. Webové rozhraní API je možné nakonfigurovat tak, aby vracelo JSON, i když koncový bod neexistuje nebo na serveru dojde k neošetřené výjimce.

Pro více informací si přečtěte Řešení chyb v aplikacích ASP.NET Core Blazor.

Sdílení zdrojů mezi doménami (Cross-Origin Resource Sharing, CORS)

Zabezpečení prohlížeče často omezuje webovou stránku v možnosti provádět požadavky na jiný původ než ten, který ji poskytl. Toto omezení se označuje jako zásada stejného zdroje. Zásady stejného původu omezují (ale nebrání) škodlivému webu číst citlivá data z jiného webu. Aby bylo možné provádět žádosti z prohlížeče do koncového bodu s jiným původem, musí koncový bod povolit sdílení prostředků mezi zdroji (CORS).

Další informace o CORS na straně serveru najdete v tématu Povolení požadavků mezi zdroji (CORS) v ASP.NET Core. Příklady článku se netýkají přímo scénářů komponent Razor, ale článek je užitečný pro pochopení obecných principů CORS.

Informace o požadavcích CORS na straně klienta najdete v ASP.NET Core Blazor WebAssembly dalších scénářích zabezpečení.

Podpora ochrany proti padělání

Chcete-li přidat podporu ochrany proti padělání do požadavku HTTP, vložte AntiforgeryStateProvider a přidejte RequestToken do kolekce hlaviček jako 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);
    ...
}

Další informace najdete v tématu ASP.NET Core Blazor ověřování a autorizace.

Blazor Příklady komponent architektury pro testování přístupu k webovému rozhraní API

Různé síťové nástroje jsou veřejně dostupné pro testování back-endových aplikací webového rozhraní API přímo, například vývojář prohlížeče Firefox. Blazor Referenční zdroj architektury zahrnuje HttpClient testovací prostředky, které jsou užitečné pro testování:

HttpClientTest soubory v úložišti dotnet/aspnetcore GitHub

Note

Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepnutí větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Dodatečné zdroje

General

Zmírnění útoků nadměrným odesíláním dat

Webová rozhraní API mohou být ohrožena útokem zvaným podvržení dat, který je také známý jako útok hromadného přiřazení. Útok na nadměrné odesílání nastane, když uživatel se zlými úmysly odešle HTML formulář POST na server, který zpracovává data pro vlastnosti, jež nejsou součástí vykresleného formuláře a které vývojář nechce, aby uživatelé mohli upravovat. Pojem "overposting" doslova znamená, že uživatel se zlými úmysly provedl nadměrné množství POST požadavků při použití formuláře.

Pokyny k zmírnění útoků nadměrného vkládání najdete v tématu Kurz: Vytvoření webového rozhraní API založeného na kontroleru s ASP.NET Core.

Server-side

Client-side