Blazor WebAssembly 應用程序中進行 HTTP 請求
翻譯自 Waqas Anwar 2021年5月13日的文章 《Making HTTP Requests in Blazor WebAssembly Apps》 [1]
在我的前篇文章《Blazor Server 應用程序中進行 HTTP 請求》中,我介紹了在 Blazor Server 應用程序中進行 HTTP 請求的相關技術,在 Blazor Server App 中您可以訪問所有的 .NET 類庫和組件。但如果您創建的是 Blazor WebAssembly 應用程序,那么您的代碼將在客戶端的瀏覽器沙箱中運行,您的選擇在某種程度上會受到限制。在本教程中,我將向您展示如何在 Blazor WebAssembly 應用程序進行 HTTP 請求。
Blazor WebAssembly 應用程序中的 HttpClient 概述
Blazor WebAssembly 應用程序使用預置的 HttpClient 服務調用 Web API。這個預置的 HttpClient 是使用瀏覽器的 Fetch API[2] 實現的,會有一些限制。HttpClient 還可以使用 Blazor JSON 幫助程序或 HttpRequestMessage 對象進行 API 調用。默認情況下,您只能向同源服務器發送 API 調用請求,不過如果第三方 API 支持跨域資源共享(CORS)的話,您也可以調用其他服務器上的 API。
命名空間 System.Net.Http.Json 為使用 System.Text.Json 執行自動序列化和反序列化的 HttpClient 提供了擴展方法。這些擴展方法將請求發送到一個 Web API URI 并處理相應的響應。常用的方法有:
- GetFromJsonAsync:發送 HTTP GET 請求,并將 JSON 響應正文解析成一個對象。
- PostAsJsonAsync:將 POST 請求發送到指定的 URI,并在請求正文中載有序列化為 JSON 的 value。
- PutAsJsonAsync:發送 HTTP PUT 請求,其中包含 JSON 編碼的內容。
要理解如何將這些方法與 HttpClient 一起使用,我們需要創建兩個項目。第一個項目是一個 Web API 項目,它向客戶端公開一個 Web API。第二個項目是 Blazor WebAssembly 應用程序,它向第一個項目中創建的 Web API 發送 HTTP 請求。
實現一個 ASP.NET Core Web API
在本節中,我們將實現一個支持跨域資源共享 (CORS) 的 Web API,以便 Blazor WebAssembly 應用程序可以調用此 API。在 Visual Studio 2019 中創建一個新的 Web API 項目 BlazorClientWebAPI。我們將創建一個簡單的 API 來返回產品列表,所以首先要在項目中創建一個 Models 文件夾,并在其中添加如下的 Product 類。
Product.cs
- public class Product
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public decimal Price { get; set; }
- }
接下來,創建一個 Controllers 文件夾并在其中添加下面的 ProductsController。該控制器簡單地從 GetProducts 方法返回一些模擬的產品數據。
ProductsController.cs
- [Route("api/[controller]")]
- [ApiController]
- public class ProductsController : ControllerBase
- {
- [HttpGet]
- public IActionResult GetProducts()
- {
- var products = new List<Product>()
- {
- new Product()
- {
- Id = 1,
- Name = "Wireless Mouse",
- Price = 29.99m
- },
- new Product()
- {
- Id = 2,
- Name = "HP Headphone",
- Price = 79.99m
- },
- new Product()
- {
- Id = 3,
- Name = "Sony Keyboard",
- Price = 119.99m
- }
- };
- return Ok(products);
- }
- }
現在如果您運行該項目,并嘗試在瀏覽器中使用 URI api/products 訪問該 API,您應該能看到以 JSON 格式返回的產品數據。
在 ASP.NET Core Web API 中啟用 CORS
默認情況下,瀏覽器安全性不允許一個網頁向除提供該網頁的域之外的其他域發送請求。這種約束稱之為同源策略。如果我們希望 Blazor WebAssembly 應用程序或其他客戶端應用程序使用上述 Web API,那么我們必須啟用跨域資源共享 (CORS)。打開 Startup.cs 文件,并在 ConfigureServices 方法中調用 AddCors 方法。
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddCors(policy =>
- {
- policy.AddPolicy("CorsPolicy", opt => opt
- .AllowAnyOrigin()
- .AllowAnyHeader()
- .AllowAnyMethod());
- });
- services.AddControllers();
- }
同時,在 Startup.cs 文件的 Configure 方法中添加以下代碼行。
- app.UseCors("CorsPolicy");
有關使用 ASP.NET Core 應用程序的 CORS 的詳細信息,請參閱 《Enable Cross-Origin Requests (CORS) in ASP.NET Core》[3]。
實現 Blazor WebAssembly 應用程序
在創建上述 Web API 項目的同一解決方案中添加一個新的 Blazor WebAssembly 應用程序項目 BlazorClientWebAPIsDemo。
我們需要確保的第一件事是,在項目文件中有 System.Net.Http.Json 的引用。如果沒有,那么您可以添加該引用。
- <Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
- <PropertyGroup>
- <TargetFramework>net5.0</TargetFramework>
- </PropertyGroup>
- <ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.1" />
- <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.1" PrivateAssets="all" />
- <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
- </ItemGroup>
- </Project>
接下來,我們需要在 Program.cs 文件中配置 HttpClient 服務。確保提供了要從 Blazor WebAssembly 應用程序調用的 Web API 的基地址。
Program.cs
- public static async Task Main(string[] args)
- {
- var builder = WebAssemblyHostBuilder.CreateDefault(args);
- builder.RootComponents.Add<App>("#app");
- builder.Services.AddScoped(sp => new HttpClient
- {
- BaseAddress = new Uri("http://localhost:5000/api/")
- });
- await builder.Build().RunAsync();
- }
為了使用產品 API,我們在 Pages 文件夾中創建一個 Products.razor 組件。該視圖非常簡單,因為它只是迭代產品列表并使用簡單的 HTML 表格來顯示它們。
Products.razor
- @page "/products"
- <h1>Products</h1>
- @if (products == null)
- {
- <p><em>Loading...</em></p>
- }
- else
- {
- <table class="table">
- <thead>
- <tr>
- <th>Id</th>
- <th>Name</th>
- <th>Price</th>
- </tr>
- </thead>
- <tbody>
- @foreach (var forecast in products)
- {
- <tr>
- <td>@forecast.Id</td>
- <td>@forecast.Name</td>
- <td>@forecast.Price</td>
- </tr>
- }
- </tbody>
- </table>
- }
創建一個代碼隱藏文件 Products.razor.cs,并將配置的 HttpClient 實例作為私有成員注入到該類中。最后,使用 GetFromJsonAsync 方法調用產品 API。
Products.razor.cs
- public partial class Products
- {
- private List<Product> products;
- [Inject]
- private HttpClient Http { get; set; }
- protected override async Task OnInitializedAsync()
- {
- products = await Http.GetFromJsonAsync<List<Product>>("products");
- }
- }
您還需要在 Blazor WebAssembly 項目中創建一個 Product 類的本地副本,以將產品 API 的結果反序列化為產品對象列表。
- public class Product
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public decimal Price { get; set; }
- }
運行該項目,您將看到從后端 Web API 加載了產品的頁面。