Bagikan melalui


Memanggil API web dari ASP.NET Core Blazor

Note

Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 10 dari artikel ini.

Warning

Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 9 dari artikel ini.

Artikel ini menjelaskan cara memanggil API web dari aplikasi Blazor .

Package

Paket ini System.Net.Http.Json menyediakan metode ekstensi untuk System.Net.Http.HttpClient dan System.Net.Http.HttpContent yang melakukan serialisasi dan deserialisasi otomatis menggunakan System.Text.Json. Paket System.Net.Http.Json disediakan oleh kerangka kerja bersama .NET dan tidak memerlukan penambahan referensi paket ke aplikasi.

Menggunakan handler token untuk panggilan API web

Blazor Web Apps dengan autentikasi OIDC dapat menggunakan pendekatan penanganan token untuk membuat permintaan keluar untuk mengamankan panggilan API ke web eksternal. Pendekatan ini digunakan oleh BlazorWebAppOidc aplikasi sampel dan BlazorWebAppOidcServer yang dijelaskan di bagian Aplikasi sampel di artikel ini.

Untuk informasi selengkapnya, lihat sumber daya berikut:

Platform identitas Microsoft untuk panggilan API web

Blazor Web Apps yang menggunakan platform identitas Microsoft dengan paket Web Microsoft Identity untuk MICROSOFT Entra ID dapat melakukan panggilan API web yang disederhanakan dengan API yang disediakan oleh Microsoft.Identity.Web.DownstreamApi paket NuGet.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Dalam file pengaturan aplikasi (appsettings.json), berikan URL dasar dan cakupan. Dalam contoh berikut, placeholder {BASE ADDRESS} adalah URL dasar dari web API. Cakupan tunggal ditentukan dengan URI ID Aplikasi ({APP ID URI} tempat penampung) dan nama cakupan ({SCOPE NAME} tempat penampung):

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

Dalam file aplikasi Program, panggil:

Anda dapat memilih untuk mengenkripsi cache dan harus selalu melakukannya dalam produksi.

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

Token cache terdistribusi dalam memori dibuat saat memanggil AddDistributedTokenCaches untuk memastikan bahwa ada implementasi dasar yang tersedia untuk penyimpanan token terdistribusi.

Aplikasi web produksi dan API web harus menggunakan cache token terdistribusi produksi (misalnya: Redis, Microsoft SQL Server, Microsoft Azure Cosmos DB).

Note

Untuk pengembangan dan pengujian lokal pada satu komputer, Anda dapat menggunakan cache token dalam memori alih-alih cache token terdistribusi:

builder.Services.AddInMemoryTokenCaches();

Kemudian dalam periode pengembangan dan pengujian, adopsi penyedia cache token terdistribusi produksi.

AddDistributedMemoryCache menambahkan implementasi IDistributedCache default untuk menyimpan item cache di memori, yang digunakan oleh Microsoft Identity Web untuk penyimpanan cache token.

AddDistributedMemoryCache memerlukan referensi paket ke Microsoft.Extensions.Caching.Memory paket NuGet.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Untuk mengonfigurasi penyedia cache terdistribusi untuk produksi, lihat Cache terdistribusi di ASP.NET Core.

Warning

Selalu ganti cache token terdistribusi dalam memori dengan penyedia cache token nyata saat menyebarkan aplikasi ke lingkungan produksi. Jika Anda gagal mengadopsi penyedia cache token terdistribusi produksi, aplikasi mungkin mengalami penurunan performa secara signifikan.

Untuk informasi selengkapnya, lihat Serialisasi cache token: Cache terdistribusi. Namun, contoh kode yang ditampilkan tidak berlaku untuk aplikasi ASP.NET Core, yang mengonfigurasi cache terdistribusi melalui AddDistributedMemoryCache, bukan AddDistributedTokenCache.

Gunakan cincin kunci Perlindungan Data bersama dalam produksi sehingga instans aplikasi di seluruh server di farm web dapat mendekripsi token saat MsalDistributedTokenCacheAdapterOptions.Encrypt diatur ke true.

Note

Untuk pengembangan awal dan pengujian lokal pada satu komputer, Anda dapat mengatur Encrypt ke false dan mengonfigurasi ring kunci Perlindungan Data bersama nanti.

options.Encrypt = false;

Kemudian dalam periode pengembangan dan pengujian, aktifkan enkripsi token dan adopsi cincin kunci Perlindungan Data bersama.

Contoh berikut menunjukkan cara menggunakan Azure Blob Storage dan Azure Key Vault (PersistKeysToAzureBlobStorage/ProtectKeysWithAzureKeyVault) untuk cincin kunci bersama. Konfigurasi layanan adalah skenario kasus dasar untuk tujuan demonstrasi. Sebelum menyebarkan aplikasi produksi, biasakan diri Anda dengan layanan Azure dan adopsi praktik terbaik menggunakan kumpulan dokumentasi khusus layanan Azure, yang ditautkan di akhir bagian ini.

Tambahkan paket berikut ke proyek server dari Blazor Web App:

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Note

Sebelum melanjutkan langkah-langkah berikut, konfirmasikan bahwa aplikasi terdaftar di Microsoft Entra.

Konfigurasikan Azure Blob Storage untuk mempertahankan kunci perlindungan data. Ikuti panduan di Penyedia penyimpanan utama di ASP.NET Core.

Konfigurasikan Azure Key Vault untuk mengenkripsi kunci perlindungan data saat tidak aktif. Ikuti panduan dalam Mengonfigurasi ASP.NET Perlindungan Data Inti.

Gunakan kode berikut dalam Program file tempat layanan terdaftar:

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 Klien Terkelola Identity Azure (GUID).

{TENANT ID}: ID Penyewa.

{APPLICATION NAME}: SetApplicationName mengatur nama unik aplikasi ini dalam sistem perlindungan data. Nilai harus konsisten di seluruh instalasi aplikasi.

{BLOB URI}: URI penuh ke file kunci. URI dihasilkan oleh Azure Storage saat Anda membuat file kunci. Jangan gunakan SAS.

{KEY IDENTIFIER}: Pengidentifikasi kunci Azure Key Vault yang digunakan untuk enkripsi kunci. Kebijakan akses memungkinkan aplikasi mengakses brankas kunci dengan Getizin , Unwrap Key, dan Wrap Key . Pengidentifikasi kunci diperoleh dari kunci di portal Entra atau Azure setelah kunci tersebut dibuat. Jika Anda mengaktifkan rotasi otomatis kunci brankas kunci, pastikan Anda menggunakan pengidentifikasi kunci tanpa versi dalam konfigurasi brankas kunci aplikasi, di mana tidak ada GUID kunci yang ditempatkan di akhir pengidentifikasi (misalnya: https://contoso.vault.azure.net/keys/data-protection).

Note

Di lingkungan non-Produksi, contoh sebelumnya menggunakan DefaultAzureCredential untuk menyederhanakan autentikasi sambil mengembangkan aplikasi yang disebarkan ke Azure dengan menggabungkan kredensial yang digunakan di lingkungan hosting Azure dengan kredensial yang digunakan dalam pengembangan lokal. Saat pindah ke produksi, memilih alternatif adalah pilihan yang lebih baik, seperti ManagedIdentityCredential yang ditunjukkan dalam contoh sebelumnya. Untuk informasi selengkapnya, lihat Mengautentikasi aplikasi .NET yang dihosting Azure ke sumber daya Azure menggunakan identitas terkelola yang ditetapkan sistem.

Suntikkan IDownstreamApi dan panggil CallApiForUserAsync saat memanggil atas nama pengguna:

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

Pendekatan ini digunakan oleh BlazorWebAppEntra aplikasi sampel dan BlazorWebAppEntraBff yang dijelaskan di bagian Aplikasi sampel di artikel ini.

Untuk informasi selengkapnya, lihat sumber daya berikut:

Aplikasi sampel

Untuk contoh yang berfungsi, lihat contoh aplikasi berikut di repositori GitHub sampel Blazor (dotnet/blazor-samples) (cara mengunduh).

BlazorWebAppCallWebApi

Panggil API daftar tugas web eksternal (bukan di Blazor Web App) dari Blazor Web App:

  • Backend: Aplikasi API web untuk mengelola daftar todo, berdasarkan Minimal APIs. Aplikasi API web adalah aplikasi terpisah dari Blazor Web App, mungkin dihosting di server yang berbeda.
  • BlazorApp / BlazorApp.Client: Sebuah Blazor Web App yang memanggil aplikasi API web dengan HttpClient untuk operasi daftar todo, seperti membuat, membaca, memperbarui, dan menghapus (CRUD) item dari daftar todo.

Untuk penyajian sisi klien (CSR), termasuk komponen WebAssembly Interaktif dan komponen Otomatis yang telah mengadopsi CSR, panggilan dilakukan dengan yang sudah dikonfigurasi HttpClient sebelumnya yang terdaftar dalam berkas proyek klien Program (BlazorApp.Client):

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

Untuk rendering sisi server (SSR), yang mencakup komponen Server yang telah dirender sebelumnya dan komponen interaktif, komponen WebAssembly yang sudah prarender, dan komponen Otomatis yang telah prarender atau telah mengadopsi SSR, panggilan dilakukan dengan HttpClient yang terdaftar dalam berkas Program dari proyek server (BlazorApp):

builder.Services.AddHttpClient();

Panggil API daftar film internal (di dalam Blazor Web App), di mana API ini berada di proyek server Blazor Web App.

  • BlazorApp: Sebuah Blazor Web App yang mengelola daftar film:
    • Saat operasi dilakukan pada daftar film dalam aplikasi di server, panggilan API biasa digunakan.
    • Saat panggilan API dilakukan oleh klien berbasis web, API web digunakan untuk operasi daftar film, berdasarkan Minimal APIs.
  • BlazorApp.Client: Proyek klien dari Blazor Web App, yang berisi komponen WebAssembly Interaktif dan Otomatis untuk pengelolaan pengguna dalam daftar film.

Untuk CSR, yang mencakup komponen Interactive WebAssembly dan komponen Otomatis yang telah mengadopsi CSR, panggilan ke API dilakukan melalui layanan berbasis klien (ClientMovieService) yang menggunakan HttpClient yang telah dikonfigurasi sebelumnya dan terdaftar dalam file Program dari proyek klien (BlazorApp.Client). Karena panggilan ini dilakukan melalui web publik atau privat, API daftar film adalah API web.

Contoh berikut mengambil daftar film dari endpoint /movies.

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

Untuk SSR, yang mencakup komponen Server prarender dan interaktif, komponen WebAssembly yang telah dirender sebelumnya, dan komponen Otomatis yang telah dirender atau telah mengadopsi SSR, panggilan dilakukan langsung melalui layanan berbasis server (ServerMovieService). API ini tidak bergantung pada jaringan, sehingga merupakan API standar untuk operasi CRUD pada daftar film.

Contoh berikut mendapatkan daftar 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();
}

Untuk informasi selengkapnya tentang cara mengamankan data film dalam skenario ini, lihat contoh data cuaca yang dijelaskan oleh Mengamankan data di Blazor Web Appdengan Penyajian Otomatis Interaktif.

BlazorWebAppCallWebApi_Weather

Aplikasi sampel data cuaca yang menggunakan penyajian streaming untuk data cuaca.

BlazorWebAssemblyCallWebApi

Memanggil API web daftar todo dari aplikasi Blazor WebAssembly.

  • Backend: Aplikasi API web untuk mengelola daftar todo, berdasarkan Minimal APIs.
  • BlazorTodo: Aplikasi Blazor WebAssembly yang memanggil API web yang telah dikonfigurasi sebelumnya untuk operasi CRUD pada daftar todo.

BlazorWebAssemblyStandaloneWithIdentity

Aplikasi Blazor WebAssembly mandiri yang diamankan dengan ASP.NET Core Identity:

  • Backend: Aplikasi API web backend yang memelihara penyimpanan identitas pengguna untuk ASP.NET Core Identity.
  • BlazorWasmAuth: Aplikasi frontend mandiri Blazor WebAssembly dengan autentikasi pengguna.

Solusi ini menunjukkan panggilan API web yang aman untuk hal berikut:

  • Mendapatkan peran pengguna yang diautentikasi.
  • Pemrosesan data untuk semua pengguna yang diautentikasi.
  • Pemrosesan data untuk pengguna yang berwenang (pengguna harus berada dalam peran Manager) melalui kebijakan otorisasi .

BlazorWebAppOidc

Blazor Web App dengan interaktivitas otomatis secara global yang menggunakan autentikasi OIDC dengan Microsoft Entra tanpa membutuhkan paket khusus untuk Entra. Sampel menunjukkan cara menggunakan handler token untuk panggilan API web untuk memanggil API web aman eksternal.

BlazorWebAppOidcServer

Blazor Web App Dengan interaktivitas Server Interaktif secara global yang menggunakan autentikasi OIDC dengan Microsoft Entra dan tidak menggunakan paket khusus Entra. Sampel menunjukkan cara mengoperkan token akses untuk memanggil API web aman eksternal.

BlazorWebAppOidcBff

Blazor Web App dengan interaktivitas Otomatis global yang menggunakan:

  • Autentikasi OIDC dengan Microsoft Entra tanpa menggunakan paket khusus Entra.
  • Pola Backend for Frontend (BFF), yang merupakan pola pengembangan aplikasi yang membuat layanan backend untuk aplikasi atau antarmuka frontend.

Solusi ini mencakup demonstrasi mendapatkan data cuaca dengan aman melalui API web eksternal ketika komponen yang mengadopsi Interactive Auto rendering dirender pada sisi klien.

BlazorWebAppEntra

Blazor Web App Dengan interaktivitas Otomatis global yang menggunakan platform identitas Microsoft dengan paket Web Microsoft Identity untuk ID Microsoft Entra. Solusi ini mencakup demonstrasi mendapatkan data cuaca dengan aman melalui API web eksternal ketika komponen yang mengadopsi Interactive Auto rendering dirender pada sisi klien.

BlazorWebAppEntraBff

Blazor Web App dengan interaktivitas Otomatis global yang menggunakan:

Solusi ini mencakup demonstrasi mendapatkan data cuaca dengan aman melalui API web eksternal ketika komponen yang mengadopsi Interactive Auto rendering dirender pada sisi klien.

Pembuangan HttpRequestMessage, HttpResponseMessage, dan HttpClient

Suatu HttpRequestMessage tanpa badan tidak memerlukan pembuangan eksplisit. Namun, Anda dapat membuangnya dengan salah satu pola berikut:

  • using deklarasi (C# 8 atau yang lebih baru):

    using var request = new HttpRequestMessage(...);
    
  • using blokir (semua rilis C#):

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

Kami sarankan untuk membuang setiap HttpRequestMessage setelah setiap penggunaan dengan alasan-alasan berikut:

  • Untuk mendapatkan peningkatan performa dengan menghindari finalizer.
  • Ini memperkuat ketahanan kode untuk masa depan jika isi permintaan pernah ditambahkan ke HttpRequestMessage yang awalnya tidak memiliki isi permintaan.
  • Untuk mencegah kemungkinan masalah fungsional jika penangan pendelegasian mengharapkan panggilan ke Dispose/DisposeAsync.
  • Lebih mudah untuk menerapkan aturan umum di mana-mana daripada mencoba mengingat kasus tertentu.

Selalu buang HttpResponseMessage instance.

Jangan pernah membuang HttpClient instans yang dibuat dengan memanggil CreateClient karena dikelola oleh kerangka kerja.

Example:

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

Skenario sisi klien untuk memanggil API web eksternal

Komponen berbasis klien memanggil API web eksternal menggunakan instans HttpClient, biasanya dibuat dengan HttpClient yang telah dikonfigurasi sebelumnya yang terdaftar dalam file Program:

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

Komponen berikut Razor membuat permintaan ke API web untuk cabang GitHub yang mirip dengan contoh Penggunaan Dasar dalam artikel Membuat permintaan HTTP menggunakan IHttpClientFactory di 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; }
    }
}

Dalam contoh sebelumnya untuk C# 12 atau yang lebih baru, dibuat array kosong ([]) untuk variabel branches. Untuk versi C# yang lebih lama yang dikompilasi dengan SDK yang lebih lama dari .NET 8, buat array kosong (Array.Empty<GitHubBranch>()).

Untuk melindungi kode dan data .NET/C#, gunakan fitur ASP.NET Core Data Protection dengan API web backend ASP.NET Core sisi server. Aplikasi Blazor WebAssembly sisi klien memanggil API web sisi server untuk fitur aplikasi yang aman dan pemrosesan data.

Aplikasi Blazor WebAssembly sering dicegah melakukan panggilan langsung lintas asal ke API web karena keamanan CORS (Cross-Origin Request Sharing) . Pengecualian umum terlihat seperti berikut ini:

Akses untuk mengambil di '{URL}' dari asal 'https://localhost:{PORT}'' telah diblokir oleh kebijakan CORS: Header 'Access-Control-Allow-Origin' tidak ada pada sumber daya yang diminta. Jika respons buram memenuhi kebutuhan Anda, atur mode permintaan ke 'no-cors' untuk mengambil sumber daya dengan CORS dinonaktifkan.

Bahkan jika Anda memanggil SetBrowserRequestMode dengan bidang BrowserRequestModeNoCors (1) yang bertujuan menghindari pengecualian sebelumnya, permintaan sering kali gagal karena pembatasan CORS pada asal API web, seperti pembatasan yang hanya memungkinkan panggilan dari asal tertentu atau pembatasan yang mencegah permintaan fetch JavaScript dari browser. Satu-satunya cara agar panggilan tersebut berhasil adalah hanya jika API web yang Anda panggil mengizinkan asal Anda memanggil asalnya dengan konfigurasi CORS yang benar. Sebagian besar API web eksternal tidak memungkinkan Anda mengonfigurasi kebijakan CORS mereka. Untuk menangani pembatasan ini, adopsi salah satu strategi berikut:

  • Kelola API web backend ASP.NET Core di sisi server Anda sendiri. Aplikasi Blazor WebAssembly sisi klien memanggil API web sisi server Anda, dan API web Anda membuat permintaan dari kode C# berbasis server (bukan browser) ke API web eksternal dengan header CORS yang benar, mengembalikan hasilnya ke aplikasi Blazor WebAssembly sisi klien Anda.

  • Gunakan layanan proksi untuk mem-proksi permintaan dari aplikasi Blazor WebAssembly sisi klien ke API web eksternal. Layanan proksi menggunakan aplikasi sisi server untuk membuat permintaan atas nama klien dan mengembalikan hasilnya setelah panggilan berhasil. Dalam contoh berikut berdasarkan CloudFlare's CORS PROXY, placeholder {REQUEST URI} adalah URI permintaan.

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

Skenario sisi server untuk memanggil API web eksternal

Komponen berbasis server memanggil API web eksternal menggunakan HttpClient instans, biasanya dibuat menggunakan IHttpClientFactory. Untuk panduan yang berlaku untuk aplikasi sisi server, lihat Membuat permintaan HTTP menggunakan IHttpClientFactory di ASP.NET Core.

Aplikasi sisi server tidak menyertakan HttpClient layanan. Memberikan ke aplikasi menggunakan infrastruktur pabrik .

Dalam file Program:

builder.Services.AddHttpClient();

Komponen berikut Razor membuat permintaan ke API web untuk cabang GitHub yang mirip dengan contoh Penggunaan Dasar dalam artikel Membuat permintaan HTTP menggunakan IHttpClientFactory di 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; }
    }
}

Dalam contoh sebelumnya untuk C# 12 atau yang lebih baru, dibuat array kosong ([]) untuk variabel branches. Untuk versi C# yang lebih lama yang dikompilasi dengan SDK yang lebih lama dari .NET 8, buat array kosong (Array.Empty<GitHubBranch>()).

Untuk contoh tambahan, lihat contoh unggahan file sisi server yang mengunggah file ke pengontrol API web dalam artikel ASP.NET Core Blazor file uploads.

Abstraksi layanan untuk panggilan API web

Bagian ini berlaku untuk Blazor Web Appyang mempertahankan API web di proyek server atau mengubah panggilan API web ke API web eksternal.

Saat menggunakan mode render interaktif WebAssembly dan Auto, komponen-komponen diprarender secara bawaan. Komponen otomatis juga awalnya dirender secara interaktif dari server sebelum Blazor bundel diunduh ke klien dan runtime sisi klien diaktifkan. Ini berarti bahwa komponen yang menggunakan mode render ini harus dirancang sehingga berhasil berjalan dari klien dan server. Jika komponen harus memanggil API berbasis proyek server atau mengubah permintaan ke API web eksternal (yang berada di luar Blazor Web App) saat berjalan pada klien, pendekatan yang direkomendasikan adalah mengabstraksi panggilan API tersebut di belakang antarmuka layanan dan menerapkan versi klien dan server layanan:

  • Versi klien memanggil API web dengan parameter yang telah dikonfigurasi sebelumnya HttpClient.
  • Versi server biasanya dapat mengakses sumber daya sisi server secara langsung. Menyuntikkan HttpClient di server yang melakukan panggilan kembali ke server tidak disarankan, karena permintaan jaringan biasanya tidak perlu. Atau, API mungkin berada di luar proyek server, tetapi abstraksi layanan untuk server diperlukan untuk mengubah permintaan dalam beberapa cara, misalnya untuk menambahkan token akses ke permintaan yang diproksi.

Saat menggunakan mode render WebAssembly, Anda juga memiliki opsi untuk menonaktifkan prarendering, sehingga komponen hanya dirender dari klien. Untuk informasi selengkapnya, lihat Komponen Prerender ASP.NET CoreRazor.

Contoh (aplikasi sampel):

  • API web daftar film pada aplikasi contoh BlazorWebAppCallWebApi.
  • API web streaming untuk merender data cuaca di aplikasi sampel BlazorWebAppCallWebApi_Weather.
  • Data cuaca dikembalikan ke klien dalam aplikasi sampel BlazorWebAppOidc (pola non-BFF) atau BlazorWebAppOidcBff (pola BFF). Aplikasi ini menunjukkan panggilan API web yang aman. Untuk informasi selengkapnya, lihat Mengamankan ASP.NET Core Blazor Web App dengan OpenID Connect (OIDC).

Blazor Web App API web eksternal

Bagian ini berlaku untuk Blazor Web Apps yang memanggil API web yang dikelola oleh proyek terpisah (eksternal), mungkin dihosting di server yang berbeda.

Blazor Web Apps biasanya merender komponen WebAssembly di sisi klien, dan komponen otomatis dirender di server selama rendering sisi server (SSR) secara statis atau interaktif. HttpClient layanan tidak terdaftar secara default dalam proyek utama Blazor Web App. Jika aplikasi dijalankan hanya dengan HttpClient layanan yang terdaftar dalam proyek .Client, seperti yang dijelaskan di bagian Tambahkan layanan HttpClient, menjalankan aplikasi menghasilkan kesalahan saat runtime.

InvalidOperationException: Tidak dapat memberikan nilai untuk properti 'Http' pada jenis '... {COMPONENT}'. Tidak ada layanan terdaftar jenis 'System.Net.Http.HttpClient'.

Gunakan salah satu pendekatan berikut:

  • Tambahkan layanan HttpClient ke proyek server untuk membuat HttpClient tersedia selama SSR. Gunakan pendaftaran layanan berikut dalam file proyek Program server:

    builder.Services.AddHttpClient();
    

    HttpClient layanan disediakan oleh kerangka kerja bersama, sehingga referensi paket dalam file proyek aplikasi tidak diperlukan.

    Contoh: Todo mencantumkan API web di BlazorWebAppCallWebApiaplikasi sampel

  • Jika pra-penyajian tidak diperlukan untuk komponen WebAssembly yang memanggil API web, nonaktifkan pra-penyajian dengan mengikuti panduan di Komponen Prerender ASP.NET CoreRazor. Jika Anda mengadopsi pendekatan ini, Anda tidak perlu menambahkan layanan HttpClient ke proyek Blazor Web App utama karena komponen tidak di-pra-rendahkan di server.

Untuk informasi selengkapnya, lihat bagian Layanan sisi klien gagal diselesaikan selama pra-penyajian di artikel Pra-penyajian .

Data yang telah dirender sebelumnya

Saat melakukan pra-penyajian, komponen merender dua kali: pertama secara statis, lalu secara interaktif. Status tidak secara otomatis mengalir dari komponen yang sudah dirender ke yang interaktif. Jika komponen melakukan operasi inisialisasi asinkron dan merender konten yang berbeda untuk status yang berbeda selama inisialisasi, seperti "Memuat..." indikator kemajuan, Anda mungkin melihat kedipan ketika komponen merender dua kali.

Anda dapat mengatasinya dengan mengalirkan status yang sebelumnya telah dirender menggunakan API Status Komponen Persisten, yang ditunjukkan BlazorWebAppCallWebApi dan BlazorWebAppCallWebApi_Weatheraplikasi contoh. Ketika komponen dirender secara interaktif, komponen dapat merender dengan cara yang sama menggunakan status yang sama. Untuk informasi selengkapnya, lihat sumber daya berikut:

Note

API Status Komponen Persisten hanya mendukung navigasi yang ditingkatkan di .NET 10 atau yang lebih baru. Untuk aplikasi yang menargetkan .NET 8 atau .NET 9, Anda dapat menonaktifkan navigasi tingkat lanjut pada tautan ke halaman dengan atribut yang data-enhance-nav disetel ke false. Untuk informasi selengkapnya, lihat ASP.NET Core Blazor routing dan navigasi.

Streaming permintaan dari sisi klien

Untuk browser berbasis Chromium (misalnya, Google Chrome dan Microsoft Edge) menggunakan protokol HTTP/2, dan HTTPS, Blazor sisi klien menggunakan Streams API untuk mengizinkan meminta streaming.

Untuk mengaktifkan streaming permintaan, atur SetBrowserRequestStreamingEnabled ke true di HttpRequestMessage.

Dalam contoh unggahan file berikut:

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

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

Permintaan untuk streaming:

  • Memerlukan protokol HTTPS dan tidak berfungsi pada HTTP/1.x.
  • Sertakan isi tetapi bukan header Content-Length. CORS dengan perintah preflight diperlukan untuk permintaan streaming lintas asal.

Untuk informasi selengkapnya tentang unggahan file dengan komponen InputFile, lihat unggahan file ASP.NET Core Blazor dan contoh di Mengunggah file ke server dengan rendering sisi klien (CSR).

HttpClient Menambahkan layanan

Panduan di bagian ini berlaku untuk skenario sisi klien.

Komponen sisi klien memanggil API web menggunakan layanan yang telah dikonfigurasi HttpClient sebelumnya, yang berfokus pada pembuatan permintaan kembali ke server asal. Konfigurasi layanan tambahan HttpClient untuk API web lainnya dapat dibuat dalam kode pengembang. Permintaan dibuat menggunakan Blazor pembantu JSON atau dengan HttpRequestMessage. Permintaan dapat mencakup konfigurasi opsi Fetch API .

Contoh konfigurasi di bagian ini hanya berguna ketika satu API web dipanggil untuk satu HttpClient instans di aplikasi. Ketika aplikasi harus memanggil beberapa API web, masing-masing dengan alamat dasar dan konfigurasinya sendiri, Anda dapat mengadopsi pendekatan berikut, yang dibahas nanti dalam artikel ini:

Pada file Program, tambahkan layanan HttpClient jika belum ada dari templat proyek Blazor yang digunakan untuk membuat aplikasi.

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

Contoh sebelumnya mengatur alamat dasar dengan builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), yang mendapatkan alamat dasar untuk aplikasi dan biasanya berasal dari <base> nilai tag href di halaman host.

Kasus penggunaan yang paling umum untuk menggunakan alamat dasar klien sendiri adalah:

  • Proyek klien (.Client) dari Blazor Web App (.NET 8 atau yang lebih baru) melakukan panggilan API web dari komponen webAssembly atau kode yang berjalan pada klien di WebAssembly ke API di aplikasi server.
  • Proyek klien (Client) aplikasi yang dihosting Blazor WebAssembly melakukan panggilan API web ke proyek server (Server). Perhatikan bahwa templat proyek Blazor WebAssembly yang dihosting tidak lagi tersedia di .NET 8 atau yang lebih baru. Namun, aplikasi yang dihosting Blazor WebAssembly tetap didukung untuk .NET 8.

Jika Anda memanggil API web eksternal (tidak berada di ruang URL yang sama dengan aplikasi klien), atur URI ke alamat dasar API web. Contoh berikut mengatur alamat dasar API web ke https://localhost:5001, tempat aplikasi API web terpisah berjalan dan siap merespons permintaan dari aplikasi klien:

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

Pembantu JSON

HttpClient tersedia sebagai layanan yang telah dikonfigurasi sebelumnya untuk membuat permintaan kembali ke server asal.

HttpClient dan pembantu JSON (System.Net.Http.Json.HttpClientJsonExtensions) juga digunakan untuk memanggil titik akhir API web pihak ketiga. HttpClientdiimplementasikan menggunakan Fetch API browser dan tunduk pada batasannya, termasuk penegakan kebijakan asal yang sama, yang dibahas nanti dalam artikel ini di bagian Berbagi Sumber Daya Lintas Asal (CORS).

Alamat dasar klien diatur ke alamat server asal. Suntikkan instans HttpClient ke dalam komponen menggunakan direktif @inject:

@using System.Net.Http
@inject HttpClient Http

Gunakan System.Net.Http.Json namespace untuk akses ke HttpClientJsonExtensions, termasuk GetFromJsonAsync, PutAsJsonAsync, dan PostAsJsonAsync.

@using System.Net.Http.Json

Bagian berikut mencakup pembantu JSON:

System.Net.Http termasuk metode tambahan untuk mengirim permintaan HTTP dan menerima respons HTTP, misalnya untuk mengirim permintaan DELETE. Untuk informasi selengkapnya, lihat bagian DELETE dan metode ekstensi tambahan.

GET dari JSON (GetFromJsonAsync)

GetFromJsonAsync mengirim permintaan HTTP GET dan mengurai isi respons JSON untuk membuat objek.

Dalam kode komponen berikut, todoItems ditampilkan oleh komponen. GetFromJsonAsync dipanggil ketika komponen selesai menginisialisasi (OnInitializedAsync).

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

POST sebagai JSON (PostAsJsonAsync)

PostAsJsonAsync mengirim permintaan POST ke URI yang ditentukan yang berisi nilai yang diserialisasikan sebagai JSON dalam isi permintaan.

Dalam kode komponen berikut, newItemName disediakan oleh elemen terikat komponen. Metode AddItem ini dipicu dengan memilih <button> elemen.

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

PostAsJsonAsync mengembalikan sebuah HttpResponseMessage. Untuk mendeserialisasi konten JSON dari pesan respons, gunakan ReadFromJsonAsync metode ekstensi. Contoh berikut membaca data cuaca JSON sebagai array:

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

PUT sebagai JSON (PutAsJsonAsync)

PutAsJsonAsync mengirim permintaan HTTP PUT dengan konten yang dikodekan JSON.

Dalam kode komponen berikut, editItem nilai untuk Name dan IsCompleted disediakan oleh elemen terikat dari komponen. Item Id diatur ketika item dipilih di bagian lain dari UI (tidak ditampilkan) dan EditItem dipanggil. Metode SaveItem ini dipicu dengan memilih <button> elemen . Contoh berikut tidak menampilkan pemuatan todoItems untuk singkatnya. Lihat bagian GET dari JSON (GetFromJsonAsync) untuk contoh memuat item.

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

PutAsJsonAsync mengembalikan sebuah HttpResponseMessage. Untuk mendeserialisasi konten JSON dari pesan respons, gunakan ReadFromJsonAsync metode ekstensi. Contoh berikut membaca data cuaca JSON sebagai array:

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

PATCH sebagai JSON (PatchAsJsonAsync)

PatchAsJsonAsync mengirim permintaan PATCH HTTP dengan konten yang dikodekan JSON.

Note

Untuk informasi selengkapnya, lihat JsonPatch di API web ASP.NET Core.

Dalam contoh berikut, PatchAsJsonAsync menerima dokumen JSON PATCH sebagai string teks biasa dengan tanda kutip yang di-escape:

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

Pada C# 11 (.NET 7), Anda dapat menyusun string JSON sebagai literal string mentah. Tentukan sintaks JSON dengan bidang StringSyntaxAttribute.Json ke atribut [StringSyntax] untuk alat analisis kode:

@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 mengembalikan sebuah HttpResponseMessage. Untuk mendeserialisasi konten JSON dari pesan respons, gunakan ReadFromJsonAsync metode ekstensi. Contoh berikut membaca data item todo dalam format JSON ke dalam array. Array kosong dibuat jika tidak ada data item yang dikembalikan oleh metode , jadi content tidak null setelah pernyataan dijalankan:

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

Ditata dengan indentasi, spasi, dan tanda kutip yang tidak diubah, dokumen PATCH yang tidak dikodekan muncul sebagai JSON berikut:

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

Untuk menyederhanakan pembuatan dokumen PATCH di aplikasi yang mengeluarkan permintaan PATCH, aplikasi dapat menggunakan dukungan .NET JSON PATCH, seperti yang ditunjukkan panduan berikut.

Microsoft.AspNetCore.JsonPatch.SystemTextJson Instal paket NuGet dan gunakan fitur API paket untuk menyusun JsonPatchDocument permintaan PATCH.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Tambahkan direktif @using untuk namespace System.Text.Json, System.Text.Json.Serialization, dan Microsoft.AspNetCore.JsonPatch.SystemTextJson ke bagian atas komponen Razor.

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

Susun JsonPatchDocument untuk TodoItem dengan IsComplete diatur ke true menggunakan metode JsonPatchDocument.Replace.

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

Microsoft.AspNetCore.JsonPatch Instal paket NuGet dan gunakan fitur API paket untuk menyusun JsonPatchDocument permintaan PATCH.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Tambahkan direktif @using untuk namespace System.Text.Json, System.Text.Json.Serialization, dan Microsoft.AspNetCore.JsonPatch ke bagian atas komponen Razor.

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

Susun JsonPatchDocument untuk TodoItem dengan IsComplete diatur ke true menggunakan metode Replace.

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

Teruskan operasi dokumen (patchDocument.Operations) ke panggilan PatchAsJsonAsync.

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

JsonSerializerOptions.DefaultIgnoreCondition diatur ke JsonIgnoreCondition.WhenWritingDefault untuk mengabaikan properti hanya jika sama dengan nilai default untuk jenisnya.

Tambahkan JsonSerializerOptions.WriteIndented yang ditetapkan ke true jika Anda ingin menyajikan payload JSON dalam format yang menarik untuk ditampilkan. Menulis JSON yang diindentasi tidak mempengaruhi pemrosesan permintaan PATCH dan biasanya tidak dilakukan dalam aplikasi yang digunakan dalam produksi untuk permintaan web API.

Ikuti panduan di artikel JsonPatch di API web ASP.NET Core untuk menambahkan tindakan pengontrol PATCH ke API web. Atau, pemrosesan permintaan PATCH dapat diimplementasikan sebagai API Minimal dengan langkah-langkah berikut.

Tambahkan referensi paket untuk Microsoft.AspNetCore.JsonPatch.SystemTextJson paket NuGet ke aplikasi API web.

Di dalam file Program, tambahkan direktif @using untuk namespace Microsoft.AspNetCore.JsonPatch.SystemTextJson.

using Microsoft.AspNetCore.JsonPatch.SystemTextJson;

Tambahkan referensi paket untuk Microsoft.AspNetCore.Mvc.NewtonsoftJson paket NuGet ke aplikasi API web.

Note

Tidak perlu menambahkan referensi paket untuk Microsoft.AspNetCore.JsonPatch paket ke aplikasi karena referensi ke Microsoft.AspNetCore.Mvc.NewtonsoftJson paket secara otomatis menambahkan referensi paket untuk Microsoft.AspNetCore.JsonPatch.

Di dalam file Program, tambahkan direktif @using untuk namespace Microsoft.AspNetCore.JsonPatch.

using Microsoft.AspNetCore.JsonPatch;

Berikan titik akhir ke alur pemrosesan permintaan API web:

app.MapPatch("/todoitems/{id}", async (long id, TodoContext db) =>
{
    if (await db.TodoItems.FindAsync(id) is TodoItem todo)
    {
        var patchDocument = 
            new JsonPatchDocument<TodoItem>().Replace(p => p.IsComplete, true);
        patchDocument.ApplyTo(todo);
        await db.SaveChangesAsync();

        return TypedResults.Ok(todo);
    }

    return TypedResults.NotFound();
});

Warning

Seperti contoh lain dalam artikel JsonPatch di web API ASP.NET Core, API PATCH yang disebutkan sebelumnya tidak melindungi API web dari serangan over-posting. Untuk informasi selengkapnya, lihat Tutorial : Membuat API web berbasis pengontrol dengan ASP.NET Core.

Untuk pengalaman PATCH yang berfungsi dengan sempurna, lihat BlazorWebAppCallWebApiaplikasi contoh.

HAPUS (DeleteAsync) dan metode ekstensi tambahan

System.Net.Http termasuk metode ekstensi tambahan untuk mengirim permintaan HTTP dan menerima respons HTTP. HttpClient.DeleteAsync digunakan untuk mengirim permintaan HTTP DELETE ke API web.

Dalam kode komponen berikut, <button> elemen memanggil DeleteItem metode . Elemen terikat <input> memberikan id item yang akan dihapus.

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

Dinamai HttpClient sebagai IHttpClientFactory

IHttpClientFactory layanan dan konfigurasi yang dinamai HttpClient didukung.

Note

Alternatif untuk menggunakan nama HttpClient dari IHttpClientFactory adalah menggunakan tipe HttpClient. Untuk informasi selengkapnya, lihat bagian Typed HttpClient .

Microsoft.Extensions.Http Tambahkan paket NuGet ke aplikasi.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Dalam file Program dari proyek klien:

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

Jika klien yang dinamai akan digunakan oleh komponen sisi klien yang telah dirender sebelumnya dari Blazor Web App, maka registrasi layanan sebelumnya harus muncul di proyek server dan proyek .Client. Di server, builder.HostEnvironment.BaseAddress digantikan oleh alamat dasar API web, yang dijelaskan lebih lanjut di bawah ini.

Contoh sisi klien sebelumnya mengatur alamat dasar dengan builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), yang mendapatkan alamat dasar untuk aplikasi sisi klien dan biasanya berasal dari <base> nilai tag href di halaman host.

Kasus penggunaan yang paling umum untuk menggunakan alamat dasar klien sendiri adalah:

  • Proyek klien (.Client) dari Blazor Web App yang melakukan panggilan API web dari komponen WebAssembly/Auto atau kode yang berjalan pada klien di WebAssembly ke API di aplikasi server di alamat host yang sama.
  • Proyek klien (Client) dari aplikasi yang dihosting Blazor WebAssembly yang melakukan panggilan API web ke proyek server (Server).

Kasus penggunaan yang paling umum untuk menggunakan alamat dasar klien sendiri ada di proyek klien (Client) aplikasi yang dihosting Blazor WebAssembly yang melakukan panggilan API web ke proyek server (Server).

Jika Anda memanggil API web eksternal (bukan di ruang URL yang sama dengan aplikasi klien) atau Anda mengonfigurasi layanan di aplikasi sisi server (misalnya untuk menangani pra-penyajian komponen sisi klien di server), atur URI ke alamat dasar API web. Contoh berikut mengatur alamat dasar API web ke https://localhost:5001, tempat aplikasi API web terpisah berjalan dan siap merespons permintaan dari aplikasi klien:

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

Dalam kode komponen berikut:

  • Instans IHttpClientFactory akan membuat sebuah HttpClient yang diberi nama.
  • Nama HttpClient digunakan untuk mengeluarkan permintaan GET untuk data prakiraan cuaca JSON dari API web di /forecast.
@inject IHttpClientFactory ClientFactory

...

@code {
    private Forecast[]? forecasts;

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

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

Aplikasi sampel menunjukkan cara melakukan panggilan API web yang bernama dalam komponen . Untuk demonstrasi kerja tambahan di aplikasi klien berdasarkan panggilan Microsoft Graph dengan nama HttpClient, lihat Menggunakan Graph API dengan ASP.NET Core Blazor WebAssembly.

Untuk demonstrasi yang berfungsi di aplikasi klien berdasarkan panggilan Microsoft Graph dengan nama HttpClient, lihat Menggunakan Graph API dengan ASP.NET Core Blazor WebAssembly.

Diketik HttpClient

HttpClient menggunakan satu atau lebih instans HttpClient dari aplikasi, baik yang default maupun yang bernama, untuk mengembalikan data dari satu atau beberapa titik akhir API web.

Note

Alternatif untuk mengetik HttpClient adalah menggunakan HttpClient yang diberi nama dari IHttpClientFactory. Untuk informasi selengkapnya, lihat bagian Disebutkan HttpClient dengan IHttpClientFactory.

Microsoft.Extensions.Http Tambahkan paket NuGet ke aplikasi.

Note

Untuk panduan tentang menambahkan paket ke aplikasi .NET, lihat artikel di bagian Menginstal dan mengelola paket di Alur kerja konsumsi paket (dokumentasi NuGet). Konfirmasikan versi paket yang benar di NuGet.org.

Contoh berikut mengeluarkan permintaan GET untuk data prakiraan cuaca JSON dari API web di /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") ?? [];
}

Dalam file Program dari proyek klien:

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

Jika klien yang diketik akan digunakan oleh komponen sisi klien Blazor Web App yang telah dirender sebelumnya, maka registrasi layanan sebelumnya harus muncul di proyek server dan proyek .Client. Di server, builder.HostEnvironment.BaseAddress digantikan oleh alamat dasar API web, yang dijelaskan lebih lanjut di bawah ini.

Contoh sebelumnya menetapkan alamat dasar dengan builder.HostEnvironment.BaseAddress (IWebAssemblyHostEnvironment.BaseAddress), yang mendapatkan alamat dasar aplikasi sisi klien dan biasanya berasal dari nilai tag <base>href di halaman host.

Kasus penggunaan yang paling umum untuk menggunakan alamat dasar klien sendiri adalah:

  • Proyek klien (.Client) dari Blazor Web App yang melakukan panggilan API web dari komponen WebAssembly/Auto atau kode yang berjalan pada klien di WebAssembly ke API di aplikasi server di alamat host yang sama.
  • Proyek klien (Client) dari aplikasi yang dihosting Blazor WebAssembly yang melakukan panggilan API web ke proyek server (Server).

Kasus penggunaan yang paling umum untuk menggunakan alamat dasar klien sendiri ada di proyek klien (Client) aplikasi yang dihosting Blazor WebAssembly yang melakukan panggilan API web ke proyek server (Server).

Jika Anda memanggil API web eksternal (bukan di ruang URL yang sama dengan aplikasi klien) atau Anda mengonfigurasi layanan di aplikasi sisi server (misalnya untuk menangani pra-penyajian komponen sisi klien di server), atur URI ke alamat dasar API web. Contoh berikut mengatur alamat dasar API web ke https://localhost:5001, tempat aplikasi API web terpisah berjalan dan siap merespons permintaan dari aplikasi klien:

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

Komponen menyuntikkan HttpClient yang bertipe untuk memanggil API web.

Dalam kode komponen berikut:

  • Sebuah instance dari ForecastHttpClient sebelumnya disuntikkan, yang menciptakan jenis HttpClient.
  • Pengetikan HttpClient digunakan untuk mengirimkan permintaan GET untuk data prakiraan cuaca JSON dari API web.
@inject ForecastHttpClient Http

...

@code {
    private Forecast[]? forecasts;

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

Aplikasi BlazorWebAppCallWebApi sampel menunjukkan cara memanggil API web dengan menggunakan HttpClient bertipe dalam komponen CallTodoWebApiCsrTypedClient. Perhatikan bahwa komponen mengadopsi penyajian sisi klien (CSR) (InteractiveWebAssembly mode render) dengan prarender, sehingga pendaftaran layanan klien yang ditik muncul dalam file Program proyek server dan proyek .Client.

Panduan di bagian ini berlaku untuk skenario sisi klien yang mengandalkan autentikasi cookie.

Untuk autentikasi berbasis cookie, yang dianggap lebih aman daripada autentikasi token pembawa, kredensial cookie dapat dikirim dengan setiap permintaan API web dengan memanggil AddHttpMessageHandler menggunakan DelegatingHandler pada HttpClient yang telah dikonfigurasi sebelumnya. Handler mengonfigurasi SetBrowserRequestCredentials dengan BrowserRequestCredentials.Include, yang menginstruksikan browser untuk mengirim kredensial pada setiap permintaan, seperti cookie atau header autentikasi HTTP, termasuk untuk permintaan lintas asal.

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

Untuk panduan tentang cara mengakses AuthenticationStateProvider dari DelegatingHandler, lihat ASP.NET Core server-side dan skenario keamanan tambahan Blazor Web App.

CookieHandler terdaftar dalam berkas Program

builder.Services.AddTransient<CookieHandler>();

Handler pesan ditambahkan ke konfigurasi awal HttpClient mana pun yang memerlukan cookie otentikasi:

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

Untuk demonstrasi, lihat Mengamankan ASP.NET Core Blazor WebAssembly dengan ASP.NET Core Identity.

Saat menyusun HttpRequestMessage, atur kredensial dan header permintaan browser secara langsung:

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

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

HttpClient dan HttpRequestMessage dengan opsi permintaan Fetch API

Panduan di bagian ini berlaku untuk skenario sisi klien yang mengandalkan autentikasi token pembawa.

HttpClient (Dokumentasi API) dan HttpRequestMessage dapat digunakan untuk menyesuaikan permintaan. Misalnya, Anda dapat menentukan metode HTTP dan header permintaan. Komponen berikut membuat POST permintaan ke titik akhir API web dan menunjukkan isi respons.

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

BlazorImplementasi sisi klien dari HttpClient menggunakan Fetch API dan mengonfigurasi opsi Fetch API khusus permintaan yang mendasarinya melalui HttpRequestMessage metode ekstensi dan WebAssemblyHttpRequestMessageExtensions. Atur opsi tambahan menggunakan metode ekstensi generik SetBrowserRequestOption . Blazor dan API Fetch yang mendasarinya tidak langsung menambahkan atau mengubah header permintaan. Untuk informasi selengkapnya tentang bagaimana agen pengguna, seperti browser, berinteraksi dengan header, lihat kumpulan dokumentasi agen pengguna eksternal dan sumber daya web lainnya.

Streaming respons diaktifkan secara default.

Memanggil HttpContent.ReadAsStreamAsync untuk HttpResponseMessage.Content (response.Content.ReadAsStreamAsync()) mengembalikan BrowserHttpReadStream (sumber referensi), bukan MemoryStream. BrowserHttpReadStream tidak mendukung operasi sinkron, seperti Stream.Read(Span<Byte>). Jika kode Anda menggunakan operasi sinkron, Anda dapat memilih untuk tidak menggunakan streaming respons atau menyalin Stream ke dalam MemoryStream sendiri.

Note

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag untuk rilis tertentu, gunakan menu dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Untuk menolak streaming respons secara global, gunakan salah satu pendekatan berikut:

  • <WasmEnableStreamingResponse> Tambahkan properti ke file proyek dengan nilai false:

    <WasmEnableStreamingResponse>false</WasmEnableStreamingResponse>
    
  • Atur DOTNET_WASM_ENABLE_STREAMING_RESPONSE variabel lingkungan ke false atau 0.

Untuk menolak streaming respons untuk permintaan individual, atur SetBrowserResponseStreamingEnabled ke false pada HttpRequestMessage (request dalam contoh berikut):

request.SetBrowserResponseStreamingEnabled(false);

Respons HTTP biasanya di-buffer untuk mengaktifkan dukungan untuk pembacaan sinkron pada konten respons. Untuk mengaktifkan dukungan untuk streaming respons, atur SetBrowserResponseStreamingEnabled ke true pada HttpRequestMessage:

request.SetBrowserResponseStreamingEnabled(true);

Secara bawaan, HttpCompletionOption.ResponseContentRead ditetapkan, sehingga HttpClient penyelesaian terjadi setelah membaca seluruh respons, termasuk konten. Agar dapat menggunakan opsi SetBrowserResponseStreamingEnabled pada file besar, atur HttpCompletionOption.ResponseHeadersRead untuk menghindari penyimpanan sementara isi file dalam memori.

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

Untuk menyertakan kredensial dalam permintaan lintas asal, gunakan SetBrowserRequestCredentials metode ekstensi:

request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

Untuk informasi selengkapnya tentang opsi Fetch API, lihat dokumen web MDN: WindowOrWorkerGlobalScope.fetch(): Parameter.

Menangani kesalahan

Menangani kesalahan respons API web dalam kode pengembang saat terjadi. Misalnya, GetFromJsonAsync mengharapkan respons JSON dari API web dengan Content-Type dari application/json. Jika respons tidak dalam format JSON, validasi konten akan menampilkan NotSupportedException.

Dalam contoh berikut, titik akhir URI untuk permintaan data prakiraan cuaca salah eja. Seharusnya URI ke WeatherForecast, tapi muncul dalam panggilan sebagai WeatherForcast, yang tidak memiliki huruf e di Forecast.

Panggilan GetFromJsonAsync mengharapkan JSON dikembalikan, tetapi API web mengembalikan HTML untuk pengecualian yang tidak tertangani dengan Content-Typetext/html. Pengecualian yang tidak tertangani terjadi karena jalur ke /WeatherForcast tidak ditemukan dan middleware tidak dapat melayani halaman atau tampilan untuk permintaan tersebut.

Pada OnInitializedAsync klien, NotSupportedException dilemparkan ketika konten respons divalidasi sebagai non-JSON. Pengecualian tertangkap dalam blok di catch, di mana logika kustom dapat mencatat kesalahan atau menyajikan pesan kesalahan yang ramah kepada pengguna.

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

Contoh sebelumnya adalah untuk tujuan demonstrasi. API web dapat dikonfigurasi untuk mengembalikan JSON bahkan ketika titik akhir tidak ada atau pengecualian yang tidak tertangani terjadi di server.

Untuk informasi selengkapnya, lihat Menangani kesalahan dalam aplikasi ASP.NET CoreBlazor.

Berbagi Sumber Daya Antar-Asal (CORS)

Keamanan browser sering membatasi halaman web dalam membuat permintaan ke asal yang berbeda dari yang menyediakan halaman web. Pembatasan ini disebut kebijakan asal yang sama. Kebijakan asal yang sama membatasi (tetapi tidak mencegah) situs berbahaya membaca data sensitif dari situs lain. Untuk membuat permintaan dari browser ke endpoint dengan asal yang berbeda, endpoint tersebut harus mengaktifkan Berbagi Sumber Daya Lintas Asal (CORS).

Untuk informasi selengkapnya tentang CORS sisi server, lihat Mengaktifkan Permintaan Lintas Asal (CORS) di ASP.NET Core. Contoh artikel tidak berkaitan langsung dengan Razor skenario komponen, tetapi artikel ini berguna untuk mempelajari konsep CORS umum.

Untuk informasi tentang permintaan CORS sisi klien, lihat skenario keamanan tambahan di ASP.NET Core.

Dukungan anti-pemalsuan

Untuk menambahkan dukungan keamanan terhadap pemalsuan ke permintaan HTTP, masukkan AntiforgeryStateProvider dan tambahkan RequestToken ke koleksi header sebagai 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);
    ...
}

Untuk informasi selengkapnya, lihat ASP.NET Core autentikasi dan otorisasiBlazor.

Blazor contoh komponen kerangka kerja untuk menguji akses API web

Berbagai alat jaringan tersedia untuk umum untuk menguji aplikasi backend API web secara langsung, seperti Pengembang Browser Firefox. Blazor sumber referensi kerangka kerja mencakup HttpClient aset pengujian yang berguna untuk pengujian:

HttpClientTest aset di repositori dotnet/aspnetcore GitHub

Note

Tautan dokumentasi ke sumber referensi .NET biasanya memuat cabang default repositori, yang mewakili pengembangan saat ini untuk rilis .NET berikutnya. Untuk memilih tag untuk rilis tertentu, gunakan menu dropdown Beralih cabang atau tag. Untuk informasi lebih lanjut, lihat Cara memilih tag versi kode sumber ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Sumber daya tambahan

General

Mitigasi serangan overposting berlebihan

API Web dapat rentan terhadap serangan pemberian akses berlebih, yang juga dikenal sebagai serangan penugasan massal. Serangan overposting terjadi ketika pengguna berbahaya mengirimkan POST pada formulir HTML ke server yang memproses data untuk properti yang tidak termasuk dalam formulir yang dirender dan yang tidak diizinkan oleh pengembang untuk dimodifikasi oleh pengguna. Istilah "overposting" secara harfiah berarti pengguna jahat telah mengirimkan permintaan POST berlebih melalui formulir.

Untuk panduan tentang mengurangi serangan overposting, lihat Tutorial : Membuat API web berbasis pengontrol dengan ASP.NET Core.

Server-side

Client-side