在 Blazor Web 应用中执行 HTTP 操作

已完成

本单元将介绍如何使用 IHttpClientFactory 来处理 HTTP 客户端的创建和处置,以及如何使用该客户端在 ASP.NET Blazor Web 应用中执行 REST 操作。 本单元中使用的代码示例基于与 API 交互,该 API 可管理存储在数据库中的水果列表。 本单元中的信息基于在 Razor 应用中使用代码隐藏文件。

以下代码表示代码示例中引用的数据模型:

public class FruitModel
{
    // An id assigned by the database
    public int id { get; set; }
    // The name of the fruit
    public string? name { get; set; }
    // A boolean to indicate if the fruit is in stock
    public bool instock { get; set; }
}

在应用中注册 IHttpClientFactory

若要在应用中添加 IHttpClientFactory,请在 Program.cs 文件中注册 AddHttpClient。 下面的代码示例使用命名客户端类型,设置 REST 操作中使用的 API 的基址,并在本单元的其余部分中引用。

// Add services to the container.
builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

// Add IHttpClientFactory to the container and set the name of the factory
// to "FruitAPI". The base address for API requests is also set.
builder.Services.AddHttpClient("FruitAPI", httpClient =>
{
    httpClient.BaseAddress = new Uri("http://localhost:5050/");
});

var app = builder.Build();

确定 API 中的操作要求

在使用 API 执行操作之前,需要确定 API 的预期内容:

  • API 终结点:确定操作的终结点,以便根据需要正确调整存储在基址中的 URI。
  • 数据要求:确定操作返回/预期的是可枚举的还是只有一条数据。

注意

本单元其余部分中的代码示例假定每个 HTTP 操作在解决方案中的单独页上进行处理。

执行 GET 操作

GET 操作不应发送正文,而是用于(如方法名称所示)从资源检索数据。 如果给定 HttpClient 和 URI,可使用 HttpClient.GetAsync 方法执行 HTTP GET 操作。 例如,如果要在 Razor Page 应用的主页 (Home.razor) 上创建一个表,以显示 GET 操作的结果,则需要将以下内容添加到代码隐藏文件 (Home.razor.cs)

  • 使用依赖项注入将 IHttpClientFactory 添加到页面模型。
  • 创建 HttpClient 的实例
  • 执行 GET 操作并将结果反序列化到数据模型中。

以下代码示例演示如何执行 GET 操作。 请务必阅读代码中的注释。

public partial class Home : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    /* Add the data model, an array is expected as a response */
    private IEnumerable<FruitModel>? _fruitList;

    // Begin GET operation when the component is initialized
    protected override async Task OnInitializedAsync()
    {
        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Perform the GET request and store the response. The parameter
        // in GetAsync specifies the endpoint in the API 
        using HttpResponseMessage response = await httpClient.GetAsync("/fruits");

        // If the request is successful deserialize the results into the data model
        if (response.IsSuccessStatusCode)
        {
            using var contentStream = await response.Content.ReadAsStreamAsync();
            _fruitList = await JsonSerializer.DeserializeAsync<IEnumerable<FruitModel>>(contentStream);
        }
        else
        {
            // If the request is unsuccessful, log the error message
            Console.WriteLine($"Failed to load fruit list. Status code: {response.StatusCode}");
        }
    }
}

执行 POST 操作

POST 操作应发送正文,并用于向资源添加数据。 如果给定 HttpClient 和 URI,可使用 HttpClient.PostAsync 方法执行 HTTP POST 操作。 如果要使用表单向主页的数据中添加项,则需要:

  • 使用依赖项注入将 IHttpClientFactory 添加到页面模型。
  • 使用 EditFormEditContext 模型将数据绑定到表单。
  • 使用 JsonSerializer.Serialize 方法序列化要添加的数据。
  • 创建 HttpClient 的实例
  • 执行 POST 操作。

注意

遵循每个 REST 操作的单独页面的项目模型,在 Add.razor 页中执行 POST 操作,代码示例位于 Add.razor.cs 代码隐藏文件中

以下代码示例演示如何执行 POST 操作。 请务必阅读代码中的注释。

namespace FruitWebApp.Components.Pages;

public partial class Add : ComponentBase
{
    // IHttpClientFactory set using dependency injection 
    [Inject]
    public required IHttpClientFactory HttpClientFactory { get; set; }

    // NavigationManager set using dependency injection
    [Inject]
    private NavigationManager? NavigationManager { get; set; }

    // Add the data model and bind the form data to it
    [SupplyParameterFromForm]
    private FruitModel? _fruitList { get; set; }

    protected override void OnInitialized() => _fruitList ??= new();

    // Begin POST operation code
    private async Task Submit()
    {
        // Serialize the information to be added to the database
        var jsonContent = new StringContent(JsonSerializer.Serialize(_fruitList),
            Encoding.UTF8,
            "application/json");

        // Create the HTTP client using the FruitAPI named factory
        var httpClient = HttpClientFactory.CreateClient("FruitAPI");

        // Execute the POST request and store the response. The response will contain the new record's ID
        using HttpResponseMessage response = await httpClient.PostAsync("/fruits", jsonContent);

        // Check if the operation was successful, and navigate to the home page if it was
        if (response.IsSuccessStatusCode)
        {
            NavigationManager?.NavigateTo("/");
        }
        else
        {
            Console.WriteLine("Failed to add fruit. Status code: {response.StatusCode}");
        }
    }
}

执行其他 REST 操作

其他操作(如 PUTDELETE )遵循前面所示的相同模型。 下表定义了常见的 REST 操作以及关联的 HttpClient 方法:

请求 方法 定义
GET HttpClient.GetAsync 检索资源
POST HttpClient.PostAsync 创建新资源
PUT HttpClient.PutAsync 更新现有资源,或创建新资源(如果不存在)
DELETE HttpClient.DeleteAsync 删除资源
PATCH HttpClient.PatchAsync 部分更新现有资源