在之前的文章在 Blazor 服务器应用程序中发出 HTTP 请求中,介绍了在 Blazor 服务器应用程序中发出 HTTP 请求的不同技术,您可以访问所有 .NET 库和组件。如果您正在创建 Blazor WebAssembly 应用程序,那么您的代码在浏览器沙箱中的客户端上运行,并且您的选择在某种程度上受到限制。在本教程中,我将向您展示如何从 Blazor WebAssembly 应用程序发出 HTTP 请求。
Blazor WebAssembly 应用程序中发出 HTTP 请求
Blazor WebAssembly 应用程序中的 HttpClient 概述
Blazor WebAssembly 应用程序使用预配置的 HttpClient 服务调用 Web API。这个预配置的 HttpClient 是使用浏览器 Fetch API 实现的,有一些限制。 HttpClient 还可以使用 Blazor JSON 帮助程序或 HttpRequestMessage 对象进行 API 调用。默认情况下,API 调用请求只能向同一源服务器发出,但您可以调用其他服务器上可用的第三方 API,如果它们支持跨源资源共享 (CORS)。
System.Net.Http.Json 命名空间为 HttpClient 提供了使用 System.Text.Json 执行自动序列化和反序列化的扩展方法。这些扩展方法将请求发送到 Web API URI 并相应地处理响应。
常用的方法有:
- GetFromJsonAsync:发送HTTP GET请求,解析JSON响应体创建对象。
- PostAsJsonAsync:向包含序列化为JSON 的值的指定 URI 发送 POST 请求 在请求正文中。
- PutAsJsonAsync:发送 HTTP PUT 请求,包括JSON 编码的内容。
要了解如何将这些方法与 HttpClient 一起使用,我们需要创建两个项目。第一个项目将是一个 Web API 项目,它将为客户端公开一个 Web API。第二个项目将是 Blazor WebAssembly App,它将向在第一个项目中创建的 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 的详细信息,请参阅在 ASP.NET Core 中启用跨域请求 (CORS)。
实现 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 加载的产品的页面。